From ad650edbef6da4b9625b7d8b93a10a3d0335fa3d Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 15 Apr 2024 13:32:00 -0400 Subject: [PATCH 01/93] initial changes to the way tags are stored --- src/queries.jl | 15 ++++++++++++--- src/states_registers.jl | 9 +++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 41a8b03..2df58ee 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -5,8 +5,10 @@ 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) +function tag!(ref::RegRef, tag::Tag, time=nothing) + push!(ref.reg.tags, tag) + push!(ref.tag_idx, size(ref.reg.tags)[1]) + push!(ref.tag_time, time) end tag!(ref, tag) = tag!(ref, Tag(tag)) @@ -23,7 +25,14 @@ 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 + if isnothing(i) + throw(KeyError(tag)) # TODO make sure there is a clear error message + else + idx = findfirst(==(i), ref.tag_idx) # everytime a tag is untagged or `querydelete!` is called the `idx` is removed from ref.tag_idx, so we won't have any duplicates + deleteat!(tags, i) + deleteat!(ref.tag_idx, idx) + deleteat!(ref.tag_time, idx) + end end diff --git a/src/states_registers.jl b/src/states_registers.jl index e5aabe8..270d2b1 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -20,12 +20,12 @@ 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 + tags::Vector{Tag} # TODO this is a rather inefficient way to store tags, but at least it provides a FIFO ordering; see issue #74 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], Vector{Tag}()) 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))) @@ -49,6 +49,11 @@ julia> r = Register(2) struct RegRef reg::Register idx::Int + tag_idx::Vector{Int} + tag_time::Vector{Float64} end +function RegRef(r::Register, idx::Int) + RegRef(r, idx, [], []) +end #Base.:(==)(r1::Register, r2::Register) = From 242024e699452cc1438fe8576e631c331171bc2a Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 17 Apr 2024 11:10:44 -0400 Subject: [PATCH 02/93] Revert "initial changes to the way tags are stored" This reverts commit ad650edbef6da4b9625b7d8b93a10a3d0335fa3d. --- src/queries.jl | 15 +++------------ src/states_registers.jl | 9 ++------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 2df58ee..41a8b03 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -5,10 +5,8 @@ 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, time=nothing) - push!(ref.reg.tags, tag) - push!(ref.tag_idx, size(ref.reg.tags)[1]) - push!(ref.tag_time, time) +function tag!(ref::RegRef, tag::Tag) + push!(ref.reg.tags[ref.idx], tag) end tag!(ref, tag) = tag!(ref, Tag(tag)) @@ -25,14 +23,7 @@ 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) - if isnothing(i) - throw(KeyError(tag)) # TODO make sure there is a clear error message - else - idx = findfirst(==(i), ref.tag_idx) # everytime a tag is untagged or `querydelete!` is called the `idx` is removed from ref.tag_idx, so we won't have any duplicates - deleteat!(tags, i) - deleteat!(ref.tag_idx, idx) - deleteat!(ref.tag_time, idx) - end + isnothing(i) ? throw(KeyError(tag)) : deleteat!(tags, i) # TODO make sure there is a clear error message end diff --git a/src/states_registers.jl b/src/states_registers.jl index 270d2b1..e5aabe8 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -20,12 +20,12 @@ struct Register # TODO better type description stateindices::Vector{Int} accesstimes::Vector{Float64} # TODO do not hardcode the type locks::Vector{Any} - tags::Vector{Tag} # TODO this is a rather inefficient way to store tags, but at least it provides a FIFO ordering; see issue #74 + 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 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}()) + Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], [Vector{Tag}() for _ in traits]) 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))) @@ -49,11 +49,6 @@ julia> r = Register(2) struct RegRef reg::Register idx::Int - tag_idx::Vector{Int} - tag_time::Vector{Float64} end -function RegRef(r::Register, idx::Int) - RegRef(r, idx, [], []) -end #Base.:(==)(r1::Register, r2::Register) = From dcbedeb8b291fcf3d4c85f9a34f0935f37b96fa0 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 1 May 2024 18:10:56 -0400 Subject: [PATCH 03/93] make the internals compatible with dictionary for query and tagging --- src/ProtocolZoo/ProtocolZoo.jl | 28 +++---- src/QuantumSavory.jl | 6 ++ src/networks.jl | 1 + src/queries.jl | 105 +++++++++++++------------ src/states_registers.jl | 5 +- test/test_entanglement_consumer.jl | 1 + test/test_entanglement_tracker.jl | 20 +++-- test/test_entanglement_tracker_grid.jl | 30 +++---- test/test_tags_and_queries.jl | 80 ++++++++++--------- 9 files changed, 143 insertions(+), 133 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index ff24c86..76d9fee 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -1,7 +1,7 @@ module ProtocolZoo using QuantumSavory -import QuantumSavory: get_time_tracker, Tag +import QuantumSavory: get_time_tracker, Tag, guid using QuantumSavory: Wildcard using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap @@ -190,9 +190,9 @@ end @yield timeout(prot.sim, prot.local_busy_time_post) # tag local node a with EntanglementCounterpart remote_node_idx_b remote_slot_idx_b - tag!(a, EntanglementCounterpart, prot.nodeB, b.idx) + tag!(a, EntanglementCounterpart, prot.nodeB, b.idx; tag_time = now(prot.sim), id = guid()) # tag local node b with EntanglementCounterpart remote_node_idx_a remote_slot_idx_a - tag!(b, EntanglementCounterpart, prot.nodeA, a.idx) + tag!(b, EntanglementCounterpart, prot.nodeA, a.idx; tag_time = now(prot.sim), id = guid()) @debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx)" unlock(a) @@ -253,18 +253,18 @@ 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) + tag!(q1, EntanglementHistory, tag1[2], tag1[3], tag2[2], tag2[3], q2.idx; tag_time = now(prot.sim), id = guid()) - 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) + tag!(q2, EntanglementHistory, tag2[2], tag2[3], tag1[2], tag1[3], q1.idx; tag_time = now(prot.sim), id = guid()) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() @@ -350,7 +350,7 @@ end apply!(localslot, updategate) end # tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx - tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid) + tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid; tag_time=now(prot.sim), id = guid()) unlock(localslot) continue end @@ -362,8 +362,8 @@ 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 - tag!(localslot, EntanglementHistory, newremotenode, newremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx) + _, _, _, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx = history[1] + tag!(localslot, EntanglementHistory, newremotenode, newremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx; tag_time=now(prot.sim), id=guid()) @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) @@ -429,8 +429,8 @@ end @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 b6928b1..9fc9569 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/networks.jl b/src/networks.jl index b0f9e53..1d5d6da 100644 --- a/src/networks.jl +++ b/src/networks.jl @@ -14,6 +14,7 @@ struct RegisterNet end function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metadata, directed_edge_metadata) + glcnt[] = 0 # set the global counter of `guid`s to zero whenever a new network is initialized 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) diff --git a/src/queries.jl b/src/queries.jl index 41a8b03..ca8a5a1 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -5,11 +5,13 @@ 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) +function tag!(ref::RegRef, tag::Tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) + id = isnothing(id) ? guid() : id + push!(ref.reg.guids, id) + ref.reg.tag_info[id] = (tag, ref.idx, tag_time) end -tag!(ref, tag) = tag!(ref, Tag(tag)) +tag!(ref, tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) = tag!(ref,Tag(tag); tag_time=tag_time, id=id) """$TYPEDSIGNATURES @@ -20,10 +22,11 @@ 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) # TODO rather slow implementation. See issue #74 + 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 @@ -125,16 +128,18 @@ julia> query(r, Int, 4, <(7)) See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) """ -function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {allB} - _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned) +function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true, ref=nothing) where {allB} + _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned, ref=ref) 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}}[] + f = filoB ? reverse : identity + for i in f(reg.guids) + slot = reg[reg.tag_info[i][2]] + if reg.tag_info[i][1] == tag && (isnothing(ref) || (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 @@ -163,20 +168,8 @@ julia> queryall(r[2], :symbol, 2, 3) (depth = 1, 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,16 +265,25 @@ function querydelete!(mb::MessageBuffer, args...) return isnothing(r) ? nothing : popat!(mb.buffer, r.depth) end +""" +$TYPEDSIGNATURES +A [`query`](@ref) for [`Register`](@ref) that also deletes the tag from the tag dictionary for the `Register`. +""" +function querydelete!(reg::Register, args...;ref=nothing) + r = query(reg, args...;ref=ref) + ret = !isnothing(r) ? reg.tag_info[r.id] : return nothing + untag!(r.slot, r.id) + return ret +end """ $TYPEDSIGNATURES -A [`query`](@ref) for [`RegRef`](@ref) that also deletes the tag from the tag list for the `RegRef`. +A [`query`](@ref) for [`RegRef`](@ref) that also deletes the tag from the tag dictionary for the `Register`. """ -function querydelete!(ref::RegRef, args...) # TODO there is a lot of code duplication here - r = query(ref, args...) - return isnothing(r) ? nothing : popat!(ref.reg.tags[ref.idx], r.depth) +function querydelete!(ref::RegRef, args...) + querydelete!(ref.reg, args...;ref=ref) end @@ -300,8 +302,8 @@ for (tagsymbol, tagvariant) in pairs(tag_types) args = (:a, :b, :c, :d, :e, :f, :g)[1:length(sig)] argssig = [:($a::$t) for (a,t) in zip(args, sig)] - eval(quote function tag!(ref::RegRef, $(argssig...)) - tag!(ref, ($tagvariant)($(args...))) + eval(quote function tag!(ref::RegRef, $(argssig...); tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) + tag!(ref, ($tagvariant)($(args...)); tag_time=tag_time, id=id) end end) eval(quote function Tag($(argssig...)) @@ -321,17 +323,16 @@ for (tagsymbol, tagvariant) in pairs(tag_types) argssig_wild = [:($a::$t) for (a,t) in zip(args, sig_wild)] 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 + 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, ref=nothing) where {allB} + 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...)) && (isnothing(ref) || (ref == slot)) + allB ? push!(res, (slot=slot, id=i, tag=tag)) : return (slot=slot, id=i, tag=tag) end end end @@ -347,13 +348,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 e5aabe8..0d721f5 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_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 1dc7b5e..2b8279a 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -13,6 +13,7 @@ end for i in 1:30, n in 3:30 + @show i, n 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 b75ac75..bf9a922 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 collect(values(net[1].tag_info))[1][1] == 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 collect(values(net[1].tag_info))[1][1] == Tag(EntanglementCounterpart, 2, 1) + @test [t[1] for t in collect(values(net[2].tag_info))] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, 3, 1)] + @test [t[1] for t in collect(values(net[3].tag_info))] == [Tag(EntanglementCounterpart, 2, 2), Tag(EntanglementCounterpart, 4, 1)] + @test [t[1] for t in collect(values(net[4].tag_info))] == [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 collect(values(net[1].tag_info))[1][1] == Tag(EntanglementCounterpart, 2, 1) + @test [t[1] for t in collect(values(net[2].tag_info))] == [Tag(EntanglementHistory, 1, 1, 3, 1, 2),Tag(EntanglementHistory, 3, 1, 1, 1, 1)] + @test [t[1] for t in collect(values(net[3].tag_info))] == [Tag(EntanglementHistory, 4, 1, 2, 2, 1), Tag(EntanglementHistory, 2, 2, 4, 1, 2)] + @test [t[1] for t in collect(values(net[4].tag_info))] == [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 2bb9969..13b4b72 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 [t[1] for t in collect(values(net[1].tag_info))] == [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 [t[1] for t in collect(values(net[1].tag_info))] == [Tag(EntanglementCounterpart, path[1], 1)] + @test [t[1] for t in collect(values(net[path[1]].tag_info))] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, path[2], 1)] + @test [t[1] for t in collect(values(net[path[2]].tag_info))] == [Tag(EntanglementCounterpart, path[3], 1), Tag(EntanglementCounterpart, path[1], 2)] + @test [t[1] for t in collect(values(net[path[3]].tag_info))] == [Tag(EntanglementCounterpart, path[2], 2), Tag(EntanglementCounterpart, path[4], 1)] + @test [t[1] for t in collect(values(net[path[4]].tag_info))] == [Tag(EntanglementCounterpart, path[5], 1), Tag(EntanglementCounterpart, path[3], 2)] + @test [t[1] for t in collect(values(net[path[5]].tag_info))] == [Tag(EntanglementCounterpart, 16, 1), Tag(EntanglementCounterpart, path[4], 2)] + @test [t[1] for t in collect(values(net[16].tag_info))] == [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 [t[1] for t in collect(values(net[1].tag_info))] == [Tag(EntanglementCounterpart, path[1], 1)] + @test [t[1] for t in collect(values(net[path[1]].tag_info))] == [Tag(EntanglementHistory, 1, 1, path[2], 1, 2), Tag(EntanglementHistory, path[2], 1, 1, 1, 1)] + @test [t[1] for t in collect(values(net[path[2]].tag_info))] == [Tag(EntanglementHistory, path[1], 2, path[3], 1, 2), Tag(EntanglementHistory, path[3], 1, path[1], 2, 1)] + @test [t[1] for t in collect(values(net[path[3]].tag_info))] == [Tag(EntanglementHistory, path[4], 1, path[2], 2, 1), Tag(EntanglementHistory, path[2], 2, path[4], 1, 2)] + @test [t[1] for t in collect(values(net[path[4]].tag_info))] == [Tag(EntanglementHistory, path[5], 1, path[3], 2, 1), Tag(EntanglementHistory, path[3], 2, path[5], 1, 2)] + @test [t[1] for t in collect(values(net[path[5]].tag_info))] == [Tag(EntanglementHistory, 16, 1, path[4], 2, 1), Tag(EntanglementHistory, path[4], 2, 16, 1, 2)] + @test [t[1] for t in collect(values(net[16].tag_info))] == [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 8e29552..9564aa7 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -8,31 +8,33 @@ using Test 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 query(r, :symbol1, 4, ❓) == (slot=r[3], id=3, tag=tag_types.SymbolIntInt(:symbol1, 4, 1)) +@test query(r, :symbol1, 4, 5) == (slot=r[2], id=2, tag=tag_types.SymbolIntInt(:symbol1, 4, 5)) +@test query(r, :symbol1, ❓, ❓) == (slot=r[3], id=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 query(r, Int, 4, 5) == (slot=r[5], id=4, 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 query(r, Int, 4, <(6)) == (slot=r[5], id=4, 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 queryall(r, :symbol1, ❓, ❓) == [(slot=r[3], id=3, tag=tag_types.SymbolIntInt(:symbol1, 4, 1)), (slot=r[2], id=2, tag=tag_types.SymbolIntInt(:symbol1, 4, 5)), (slot=r[1], id=1, tag=tag_types.SymbolIntInt(: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 query(r[2], Tag(:symbol1, 4, 5)) == (slot=r[2], id=2, tag=tag_types.SymbolIntInt(:symbol1, 4, 5)) +@test queryall(r[2], Tag(:symbol1, 4, 5)) == [(slot=r[2], id=2, tag=Tag(:symbol1, 4, 5))] +@test query(r[2], :symbol1, 4, 5) == (slot=r[2], id=2, tag=Tag(:symbol1, 4, 5)) +@test queryall(r[2], :symbol1, 4, 5) == [(slot=r[2], id=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 query(r[2], :symbol1, 4, ❓) == (slot=r[2], id=2, tag=Tag(:symbol1, 4, 5)) +@test queryall(r[2], :symbol1, 4, ❓) == [(slot=r[2], id=2, tag=Tag(:symbol1, 4, 5))] -@test querydelete!(r[2], :symbol1, 4, ❓) == Tag(:symbol1, 4, 5) +@test querydelete!(r[2], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 5), 2, nothing) @test querydelete!(r[2], :symbol1, 4, ❓) === nothing +@test querydelete!(r[3], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 1), 3, nothing) # tests for fifo and filo order queries (default is filo) @@ -49,25 +51,25 @@ tag!(reg[3], EntanglementCounterpart, 2, 20) 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 query(reg[3], EntanglementCounterpart, 1, 10) == (slot = reg[3], id = 12, tag = Tag(EntanglementCounterpart,1,10)) +@test query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=false) == (slot = reg[3], id = 5, tag = Tag(EntanglementCounterpart,1,10)) +@test query(reg[3], EntanglementCounterpart, 1, 10, Val(false); filo=true) == (slot = reg[3], id = 12, tag = Tag(EntanglementCounterpart,1,10)) -@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 query(reg[3], EntanglementCounterpart, 2, ❓) == (slot = reg[3], id = 11, tag = Tag(EntanglementCounterpart,2,20)) +@test query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=false) == (slot = reg[3], id = 6, tag = Tag(EntanglementCounterpart,2,20)) +@test query(reg[3], EntanglementCounterpart, 2, ❓, Val(false); filo=true) == (slot = reg[3], id = 11, tag = Tag(EntanglementCounterpart,2,20)) @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, 1, 10) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,1,10)) for i in (12, 9, 5)] +@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=false) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,1,10)) for i in (5, 9, 12)] +@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=true) == [(slot = reg[3], id = 12, tag = Tag(EntanglementCounterpart,1,10)) for i in (12, 9, 5)] -@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)] +@test queryall(reg[3], EntanglementCounterpart, 2, ❓) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,2,20)) for i in (11, 8, 6)] +@test queryall(reg[3], EntanglementCounterpart, 2, ❓; filo=false) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,2,20)) for i in (6, 8, 11)] +@test queryall(reg[3], EntanglementCounterpart, 2, ❓; filo=true) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,2,20)) for i in (11, 8, 6)] # tests for fifo and filo order queries (default is filo) -# for RegRefs +# for Register reg = Register(5) for i in 2:4 @@ -82,24 +84,24 @@ 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 query(reg, EntanglementCounterpart, 1, 12) == (slot = reg[2], id = 13, 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 query(reg, Tag(EntanglementCounterpart, 1, 12)) == (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart,1,12)) +@test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=false) == (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart,1,12)) +@test query(reg, EntanglementCounterpart, 1, 12, Val(false); filo=true) == (slot = reg[2], id = 13, 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 query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=false) == (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart,1,12)) +@test query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=true) == (slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart,1,314)) -@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 queryall(reg, EntanglementCounterpart, 1, ❓) == [(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))] +@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=true) == [(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))] +@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=false) == reverse([(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))]) -@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 query(reg, EntanglementCounterpart, 2, 22) == (slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)) +@test queryall(reg, EntanglementCounterpart, 2, 22) == [(slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 14, tag = Tag(EntanglementCounterpart,2,22))] +@test queryall(reg, Tag(EntanglementCounterpart, 2, 22)) == [(slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 14, 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 queryall(reg, Tag(EntanglementCounterpart, 2, 22); filo=false) == [(slot = reg[2], id = 14, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 19, 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) From 42342a3d003de7db113e18485388e3b583a93d44 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 1 May 2024 19:18:28 -0400 Subject: [PATCH 04/93] fix typo --- test/test_tags_and_queries.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index 4c680a1..3016d95 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -62,7 +62,7 @@ tag!(reg[3], EntanglementCounterpart, 1, 10) @test queryall(reg, EntanglementCounterpart, 1, 11) == [] @test queryall(reg[3], EntanglementCounterpart, 1, 10) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,1,10)) for i in (12, 9, 5)] @test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=false) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,1,10)) for i in (5, 9, 12)] -@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=true) == [(slot = reg[3], id = 12, tag = Tag(EntanglementCounterpart,1,10)) for i in (12, 9, 5)] +@test queryall(reg[3], EntanglementCounterpart, 1, 10; filo=true) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,1,10)) for i in (12, 9, 5)] @test queryall(reg[3], EntanglementCounterpart, 2, ❓) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,2,20)) for i in (11, 8, 6)] @test queryall(reg[3], EntanglementCounterpart, 2, ❓; filo=false) == [(slot = reg[3], id = i, tag = Tag(EntanglementCounterpart,2,20)) for i in (6, 8, 11)] From 1935828e4f23874fe2b1cc7c2de40b4f69f1caa8 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 2 May 2024 15:52:25 -0400 Subject: [PATCH 05/93] Complete missing `querydelete!` tests --- src/queries.jl | 12 ++++++------ test/test_tags_and_queries.jl | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 43eda6a..89dcd37 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -260,8 +260,8 @@ t=1.0: query returns nothing t=3.0: query returns SymbolIntInt(:second_tag, 123, 456)::Tag received from node 3 ``` """ -function querydelete!(mb::MessageBuffer, args...) - r = query(mb, args...) +function querydelete!(mb::MessageBuffer, args...;filo=true) + r = query(mb, args...;filo=filo) return isnothing(r) ? nothing : popat!(mb.buffer, r.depth) end @@ -270,8 +270,8 @@ $TYPEDSIGNATURES A [`query`](@ref) for [`Register`](@ref) that also deletes the tag from the tag dictionary for the `Register`. """ -function querydelete!(reg::Register, args...;ref=nothing) - r = query(reg, args...;ref=ref) +function querydelete!(reg::Register, args...;ref=nothing, filo=true) + r = query(reg, args...;ref=ref, filo=filo) ret = !isnothing(r) ? reg.tag_info[r.id] : return nothing untag!(r.slot, r.id) return ret @@ -283,8 +283,8 @@ $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. """ -function querydelete!(ref::RegRef, args...) - querydelete!(ref.reg, args...;ref=ref) +function querydelete!(ref::RegRef, args...;filo=true) + querydelete!(ref.reg, args...;ref=ref,filo=filo) end diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index 3016d95..df7cdd3 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -114,8 +114,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)] \ No newline at end of file From c1aa85dbfc151c0b74a745b5dc9ba545032252f4 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 2 May 2024 16:41:31 -0400 Subject: [PATCH 06/93] simplify tests --- src/queries.jl | 2 +- test/test_entanglement_tracker.jl | 18 ++++++++-------- test/test_entanglement_tracker_grid.jl | 30 +++++++++++++------------- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 89dcd37..24abb26 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -261,7 +261,7 @@ t=3.0: query returns SymbolIntInt(:second_tag, 123, 456)::Tag received from node ``` """ function querydelete!(mb::MessageBuffer, args...;filo=true) - r = query(mb, args...;filo=filo) + r = query(mb, args...) return isnothing(r) ? nothing : popat!(mb.buffer, r.depth) end diff --git a/test/test_entanglement_tracker.jl b/test/test_entanglement_tracker.jl index bf9a922..afc4230 100644 --- a/test/test_entanglement_tracker.jl +++ b/test/test_entanglement_tracker.jl @@ -28,7 +28,7 @@ for i in 1:10 @process entangler1() run(sim, 20) - @test collect(values(net[1].tag_info))[1][1] == 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() @@ -37,10 +37,10 @@ for i in 1:10 @process entangler3() run(sim, 60) - @test collect(values(net[1].tag_info))[1][1] == Tag(EntanglementCounterpart, 2, 1) - @test [t[1] for t in collect(values(net[2].tag_info))] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, 3, 1)] - @test [t[1] for t in collect(values(net[3].tag_info))] == [Tag(EntanglementCounterpart, 2, 2), Tag(EntanglementCounterpart, 4, 1)] - @test [t[1] for t in collect(values(net[4].tag_info))] == [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 @@ -52,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 collect(values(net[1].tag_info))[1][1] == Tag(EntanglementCounterpart, 2, 1) - @test [t[1] for t in collect(values(net[2].tag_info))] == [Tag(EntanglementHistory, 1, 1, 3, 1, 2),Tag(EntanglementHistory, 3, 1, 1, 1, 1)] - @test [t[1] for t in collect(values(net[3].tag_info))] == [Tag(EntanglementHistory, 4, 1, 2, 2, 1), Tag(EntanglementHistory, 2, 2, 4, 1, 2)] - @test [t[1] for t in collect(values(net[4].tag_info))] == [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]) diff --git a/test/test_entanglement_tracker_grid.jl b/test/test_entanglement_tracker_grid.jl index 13b4b72..a21977b 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 [t[1] for t in collect(values(net[1].tag_info))] == [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 [t[1] for t in collect(values(net[1].tag_info))] == [Tag(EntanglementCounterpart, path[1], 1)] - @test [t[1] for t in collect(values(net[path[1]].tag_info))] == [Tag(EntanglementCounterpart, 1, 1), Tag(EntanglementCounterpart, path[2], 1)] - @test [t[1] for t in collect(values(net[path[2]].tag_info))] == [Tag(EntanglementCounterpart, path[3], 1), Tag(EntanglementCounterpart, path[1], 2)] - @test [t[1] for t in collect(values(net[path[3]].tag_info))] == [Tag(EntanglementCounterpart, path[2], 2), Tag(EntanglementCounterpart, path[4], 1)] - @test [t[1] for t in collect(values(net[path[4]].tag_info))] == [Tag(EntanglementCounterpart, path[5], 1), Tag(EntanglementCounterpart, path[3], 2)] - @test [t[1] for t in collect(values(net[path[5]].tag_info))] == [Tag(EntanglementCounterpart, 16, 1), Tag(EntanglementCounterpart, path[4], 2)] - @test [t[1] for t in collect(values(net[16].tag_info))] == [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 [t[1] for t in collect(values(net[1].tag_info))] == [Tag(EntanglementCounterpart, path[1], 1)] - @test [t[1] for t in collect(values(net[path[1]].tag_info))] == [Tag(EntanglementHistory, 1, 1, path[2], 1, 2), Tag(EntanglementHistory, path[2], 1, 1, 1, 1)] - @test [t[1] for t in collect(values(net[path[2]].tag_info))] == [Tag(EntanglementHistory, path[1], 2, path[3], 1, 2), Tag(EntanglementHistory, path[3], 1, path[1], 2, 1)] - @test [t[1] for t in collect(values(net[path[3]].tag_info))] == [Tag(EntanglementHistory, path[4], 1, path[2], 2, 1), Tag(EntanglementHistory, path[2], 2, path[4], 1, 2)] - @test [t[1] for t in collect(values(net[path[4]].tag_info))] == [Tag(EntanglementHistory, path[5], 1, path[3], 2, 1), Tag(EntanglementHistory, path[3], 2, path[5], 1, 2)] - @test [t[1] for t in collect(values(net[path[5]].tag_info))] == [Tag(EntanglementHistory, 16, 1, path[4], 2, 1), Tag(EntanglementHistory, path[4], 2, 16, 1, 2)] - @test [t[1] for t in collect(values(net[16].tag_info))] == [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]) From 1c49cd8536e49a4cc83ece9877662a77e8d66175 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 2 May 2024 21:23:26 -0400 Subject: [PATCH 07/93] Fixes to doctests --- src/queries.jl | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 24abb26..2e6bcf9 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -2,8 +2,6 @@ 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; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) id = isnothing(id) ? guid() : id @@ -18,8 +16,6 @@ tag!(ref, tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Noth 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, id::Int128) # TODO rather slow implementation. See issue #74 @@ -65,15 +61,15 @@ julia> r = Register(10); 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) + (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) + (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::128, tag::Tag}[] ``` """ queryall(args...; filo=true, kwargs...) = query(args..., Val{true}(); filo, kwargs...) @@ -98,7 +94,7 @@ julia> r = Register(10); 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]); @@ -106,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 @@ -123,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) @@ -134,8 +130,8 @@ 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, ref=nothing) where {allB, filoB} result = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] - f = filoB ? reverse : identity - for i in f(reg.guids) + 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 && (isnothing(ref) || (ref == slot)) # Need to check slot when calling from `query` dispatch on RegRef if _nothingor(locked, islocked(slot) && _nothingor(assigned, isassigned(slot))) @@ -158,14 +154,14 @@ 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) + (slot = Slot 2, id = 6, tag = SymbolIntInt(:symbol, 2, 3)::Tag) ``` """ 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} From f847609d3b46120bfa81412d28508b3a8db1ef57 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 2 May 2024 21:47:45 -0400 Subject: [PATCH 08/93] fix --- src/queries.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 2e6bcf9..aadf605 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -60,16 +60,16 @@ julia> r = Register(10); tag!(r[2], :symbol, 4, 5); julia> queryall(r, :symbol, ❓, ❓) -2-element Vector{@NamedTuple{slot::RegRef, depth::Int64, tag::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}}: +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, id::128, tag::Tag}[] +@NamedTuple{slot::RegRef, id::Int128, tag::Tag}[] ``` """ queryall(args...; filo=true, kwargs...) = query(args..., Val{true}(); filo, kwargs...) @@ -160,7 +160,7 @@ julia> query(r[3], :symbol, 2, 3) === nothing true julia> queryall(r[2], :symbol, 2, 3) -1-element Vector{@NamedTuple{depth::Int64, tag::Tag}}: +1-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: (slot = Slot 2, id = 6, tag = SymbolIntInt(:symbol, 2, 3)::Tag) ``` """ From f82afbea9bffb5f02eee477cb18b0fb2a16498ba Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Fri, 3 May 2024 20:49:03 -0400 Subject: [PATCH 09/93] apply suggestions from code review --- src/ProtocolZoo/ProtocolZoo.jl | 14 +++++++------- src/networks.jl | 1 - src/queries.jl | 5 +++-- test/test_entanglement_consumer.jl | 1 - 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 76d9fee..de684dc 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -1,7 +1,7 @@ module ProtocolZoo using QuantumSavory -import QuantumSavory: get_time_tracker, Tag, guid +import QuantumSavory: get_time_tracker, Tag using QuantumSavory: Wildcard using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap @@ -190,9 +190,9 @@ end @yield timeout(prot.sim, prot.local_busy_time_post) # tag local node a with EntanglementCounterpart remote_node_idx_b remote_slot_idx_b - tag!(a, EntanglementCounterpart, prot.nodeB, b.idx; tag_time = now(prot.sim), id = guid()) + 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; tag_time = now(prot.sim), id = guid()) + tag!(b, EntanglementCounterpart, prot.nodeA, a.idx) @debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx)" unlock(a) @@ -260,11 +260,11 @@ end 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; tag_time = now(prot.sim), id = guid()) + tag!(q1, EntanglementHistory, tag1[2], tag1[3], tag2[2], tag2[3], q2.idx) 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; tag_time = now(prot.sim), id = guid()) + tag!(q2, EntanglementHistory, tag2[2], tag2[3], tag1[2], tag1[3], q1.idx) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() @@ -350,7 +350,7 @@ end apply!(localslot, updategate) end # tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx - tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid; tag_time=now(prot.sim), id = guid()) + tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid) unlock(localslot) continue end @@ -363,7 +363,7 @@ end if !isnothing(history) # @debug "tracker @$(prot.node) history: $(history) | msg: $msg" _, _, _, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx = history[1] - tag!(localslot, EntanglementHistory, newremotenode, newremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx, swappedlocal_slotidx; tag_time=now(prot.sim), id=guid()) + 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) put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) diff --git a/src/networks.jl b/src/networks.jl index 1d5d6da..b0f9e53 100644 --- a/src/networks.jl +++ b/src/networks.jl @@ -14,7 +14,6 @@ struct RegisterNet end function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metadata, directed_edge_metadata) - glcnt[] = 0 # set the global counter of `guid`s to zero whenever a new network is initialized 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) diff --git a/src/queries.jl b/src/queries.jl index aadf605..10942aa 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -4,6 +4,7 @@ Assign a tag to a slot in a register. See also: [`query`](@ref), [`untag!`](@ref)""" function tag!(ref::RegRef, tag::Tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) + tag_time = isnothing(tag_time) ? now(get_time_tracker(ref)) : tag_time id = isnothing(id) ? guid() : id push!(ref.reg.guids, id) ref.reg.tag_info[id] = (tag, ref.idx, tag_time) @@ -299,8 +300,8 @@ for (tagsymbol, tagvariant) in pairs(tag_types) args = (:a, :b, :c, :d, :e, :f, :g)[1:length(sig)] argssig = [:($a::$t) for (a,t) in zip(args, sig)] - eval(quote function tag!(ref::RegRef, $(argssig...); tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) - tag!(ref, ($tagvariant)($(args...)); tag_time=tag_time, id=id) + eval(quote function tag!(ref::RegRef, $(argssig...); kwa...) + tag!(ref, ($tagvariant)($(args...)); kwa...) end end) eval(quote function Tag($(argssig...)) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 2b8279a..1dc7b5e 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -13,7 +13,6 @@ end for i in 1:30, n in 3:30 - @show i, n net = RegisterNet([Register(10) for j in 1:n]) sim = get_time_tracker(net) From b702261bacb18552c5db09563f64398353a87d0c Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Fri, 3 May 2024 21:03:29 -0400 Subject: [PATCH 10/93] update test_tags_and_queries.jl --- test/test_tags_and_queries.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index df7cdd3..cb8b9ec 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -32,9 +32,9 @@ tag!(r[5], Int, 4, 5) @test query(r[2], :symbol1, 4, ❓) == (slot=r[2], id=2, tag=Tag(:symbol1, 4, 5)) @test queryall(r[2], :symbol1, 4, ❓) == [(slot=r[2], id=2, tag=Tag(:symbol1, 4, 5))] -@test querydelete!(r[2], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 5), 2, nothing) +@test querydelete!(r[2], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 5), 2, 0.0) @test querydelete!(r[2], :symbol1, 4, ❓) === nothing -@test querydelete!(r[3], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 1), 3, nothing) +@test querydelete!(r[3], :symbol1, 4, ❓) == (Tag(:symbol1, 4, 1), 3, 0.0) # tests for fifo and filo order queries (default is filo) From 13c7a058bb5ed8de81c11d9bed9a5980221365d0 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 7 May 2024 20:14:30 -0400 Subject: [PATCH 11/93] use `_querydelete` for both registers and refs --- src/queries.jl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 10942aa..c1cdad4 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -267,8 +267,12 @@ $TYPEDSIGNATURES A [`query`](@ref) for [`Register`](@ref) that also deletes the tag from the tag dictionary for the `Register`. """ -function querydelete!(reg::Register, args...;ref=nothing, filo=true) - r = query(reg, args...;ref=ref, filo=filo) +function querydelete!(reg::Register, args...; kwa...) + _querydelete(reg, args...; filo=filo) +end + +function _querydelete!(reg::Register, args...; kwa...) + r = query(reg, args...; kwa...) ret = !isnothing(r) ? reg.tag_info[r.id] : return nothing untag!(r.slot, r.id) return ret @@ -280,8 +284,8 @@ $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. """ -function querydelete!(ref::RegRef, args...;filo=true) - querydelete!(ref.reg, args...;ref=ref,filo=filo) +function querydelete!(ref::RegRef, args...; filo=true) + _querydelete!(ref.reg, args...;ref=ref,filo=filo) end From b9481d6f42e6489db743562fd67c9c2a5b8ed49c Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 7 May 2024 20:16:01 -0400 Subject: [PATCH 12/93] Version bump for breaking release --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 3abbbec..ee45d01 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" From 691911f970cc16804c42da2123273133ae0cfa05 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 7 May 2024 21:23:10 -0400 Subject: [PATCH 13/93] some more refinement on query interface --- src/queries.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index c1cdad4..d80e5d3 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -125,8 +125,8 @@ julia> query(r, Int, 4, <(7)) See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) """ -function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true, ref=nothing) where {allB} - _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned, ref=ref) +function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {allB} + _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, ref=nothing) where {allB, filoB} @@ -267,12 +267,12 @@ $TYPEDSIGNATURES A [`query`](@ref) for [`Register`](@ref) that also deletes the tag from the tag dictionary for the `Register`. """ -function querydelete!(reg::Register, args...; kwa...) - _querydelete(reg, args...; filo=filo) +function querydelete!(reg::Register, args...; filo=true, kwa...) + _querydelete(reg, args...; filo=filo, kwa...) end -function _querydelete!(reg::Register, args...; kwa...) - r = query(reg, args...; kwa...) +function _querydelete!(reg::Register, args...; ref=nothing, kwa...) + r = isnothing(ref) ? query(reg, args..., Val{false}(); kwa...) : query(ref, args..., Val{false}(), ; kwa...) ret = !isnothing(r) ? reg.tag_info[r.id] : return nothing untag!(r.slot, r.id) return ret @@ -284,8 +284,8 @@ $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. """ -function querydelete!(ref::RegRef, args...; filo=true) - _querydelete!(ref.reg, args...;ref=ref,filo=filo) +function querydelete!(ref::RegRef, args...; filo=true, kwa...) + _querydelete!(ref.reg, args...;filo=filo, ref=ref, kwa...) end @@ -325,7 +325,7 @@ for (tagsymbol, tagvariant) in pairs(tag_types) argssig_wild = [:($a::$t) for (a,t) in zip(args, sig_wild)] 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, ref=nothing) where {allB} + 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, :id, :tag), Tuple{RegRef, Int128, Tag}}[] op_guid = filo ? reverse : identity for i in op_guid(reg.guids) @@ -333,7 +333,7 @@ for (tagsymbol, tagvariant) in pairs(tag_types) 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...)) && (isnothing(ref) || (ref == slot)) + 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 From 68273649f20714a325573525b36a5110f0b3cfc8 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 7 May 2024 21:33:43 -0400 Subject: [PATCH 14/93] update queries.jl --- src/queries.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/queries.jl b/src/queries.jl index d80e5d3..2be7a89 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -56,6 +56,7 @@ $TYPEDSIGNATURES A query function that returns all slots of a register that have a given tag, with support for predicates and wildcards. ```jldoctest +julia> QuantumSavory.glcnt[] = 0; julia> r = Register(10); tag!(r[1], :symbol, 2, 3); tag!(r[2], :symbol, 4, 5); From 0900da9025d57e0597753419e1d71d82568b8cff Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Wed, 8 May 2024 13:17:44 -0400 Subject: [PATCH 15/93] Update queries.jl --- src/queries.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/queries.jl b/src/queries.jl index 2be7a89..657ad13 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -57,6 +57,7 @@ A query function that returns all slots of a register that have a given tag, wit ```jldoctest julia> QuantumSavory.glcnt[] = 0; + julia> r = Register(10); tag!(r[1], :symbol, 2, 3); tag!(r[2], :symbol, 4, 5); From 0540e90748b945d6d24f4d2d9f63b6008114c6bd Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 16 May 2024 14:42:54 -0400 Subject: [PATCH 16/93] Apply suggestions from code review --- src/queries.jl | 9 ++++----- test/test_tags_and_queries.jl | 16 ++++++++++------ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 657ad13..154fa92 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -3,14 +3,13 @@ Assign a tag to a slot in a register. See also: [`query`](@ref), [`untag!`](@ref)""" -function tag!(ref::RegRef, tag::Tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) - tag_time = isnothing(tag_time) ? now(get_time_tracker(ref)) : tag_time - id = isnothing(id) ? guid() : id +function tag!(ref::RegRef, tag::Tag) + id = guid() push!(ref.reg.guids, id) - ref.reg.tag_info[id] = (tag, ref.idx, tag_time) + ref.reg.tag_info[id] = (tag, ref.idx, now(get_time_tracker(ref))) end -tag!(ref, tag; tag_time::Union{Float64, Nothing}=nothing, id::Union{Int128, Nothing}=nothing) = tag!(ref,Tag(tag); tag_time=tag_time, id=id) +tag!(ref, tag) = tag!(ref,Tag(tag)) """$TYPEDSIGNATURES diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index cb8b9ec..fec1ffd 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -5,6 +5,10 @@ using Test @test tag_types.SymbolIntInt(:symbol1, 4, 5) == Tag(:symbol1, 4, 5) +function strip_id(info_vector) + return [(slot=n.slot, tag=n.tag) for n in info_vector] +end + r = Register(10) tag!(r[1], :symbol1, 2, 3) tag!(r[2], :symbol1, 4, 5) @@ -95,15 +99,15 @@ end @test query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=false) == (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart,1,12)) @test query(reg, EntanglementCounterpart, 1, ❓, Val(false); filo=true) == (slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart,1,314)) -@test queryall(reg, EntanglementCounterpart, 1, ❓) == [(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))] -@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=true) == [(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))] -@test queryall(reg, EntanglementCounterpart, 1, ❓; filo=false) == reverse([(slot = reg[4], id = 36, tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], id = 33, tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], id = 29, tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], id = 28, tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], id = 25, tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], id = 21, tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], id = 20, tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], id = 17, tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], id = 13, tag = Tag(EntanglementCounterpart, 1, 12))]) +@test strip_id(queryall(reg, EntanglementCounterpart, 1, ❓)) == [(slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 12))] +@test strip_id(queryall(reg, EntanglementCounterpart, 1, ❓; filo=true)) == [(slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 12))] +@test strip_id(queryall(reg, EntanglementCounterpart, 1, ❓; filo=false)) == reverse([(slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 314)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 114)), (slot = reg[4], tag = Tag(EntanglementCounterpart, 1, 14)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 313)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 113)), (slot = reg[3], tag = Tag(EntanglementCounterpart, 1, 13)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 312)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 112)), (slot = reg[2], tag = Tag(EntanglementCounterpart, 1, 12))]) @test query(reg, EntanglementCounterpart, 2, 22) == (slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)) -@test queryall(reg, EntanglementCounterpart, 2, 22) == [(slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 14, tag = Tag(EntanglementCounterpart,2,22))] -@test queryall(reg, Tag(EntanglementCounterpart, 2, 22)) == [(slot = reg[2], id = 19, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 14, tag = Tag(EntanglementCounterpart,2,22))] +@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) == [(slot = reg[2], id = 14, tag = Tag(EntanglementCounterpart,2,22)), (slot = reg[2], id = 19, 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) From a897ede37a8930674deeb064817da357f4b898ad Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 21 Feb 2024 08:37:12 -0500 Subject: [PATCH 17/93] added repeater grid example and started how-to tutorial with animation --- docs/src/howto/repeater_grid/grid_sim6x6.mp4 | Bin 0 -> 169045 bytes docs/src/howto/repeater_grid/repeater_grid.md | 10 ++ examples/repeater_grid/repeater_grid.jl | 86 ++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 docs/src/howto/repeater_grid/grid_sim6x6.mp4 create mode 100644 docs/src/howto/repeater_grid/repeater_grid.md create mode 100644 examples/repeater_grid/repeater_grid.jl diff --git a/docs/src/howto/repeater_grid/grid_sim6x6.mp4 b/docs/src/howto/repeater_grid/grid_sim6x6.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..a4ac9b2ae5e9fa6a9dfc18feddd51d34e239d8ab GIT binary patch literal 169045 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%0D7m|wJ^IbMD~gyH@i!V6g;@2Q22^?nPh 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 `NIAEZB)?lISJQyFFaH1aRaje9yVg5WQ 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

+hGitrc$uJ+iH{& z4Hb6kej2r`lFR3HX_H=~kt&kHDnFR#cC6wuYCu7!OpEFxr5haYI&lX}U)-*YA}Y}h+1YAC zbM7`>*A^L{=?tzkt}O>x%{*f+-ox7;U>N{&SOeze&E2qB{vNcU5z)OFUk3@cKwfGI zN`mBrFdT(}j4dW8^9oKtSu zEgHLk!vH_Z}-6KhunBm5gbDIDObW1 zI5{FXP5-KWxjAQ+>Q!9k%O(Y^iB^g&ADuS@C|Q{Zq6S+2|F%-5QK*06CU>UKq1v8J z%EL%#%dX3MsAhoXl0hUkop27y)N7~mN_LQ0LyWvR^I}F#e0_YXxb36X{Ue4YaGur4 z3$sY6TK^DBVZ;DsW0H1{UGmi}c6eICBNjKeb)lWbNPOnD$;=rZF=-cY+&QRfpnkYy z*=`M?gK8)V|C#x(0%^>crq z47o`aT)p&6^?b#D5K8H^Tv+0uZ9nIT1GrmMwVe?SbumU)&mo`^OVRWu%5}}$^ zLUE%+>vzR0&QGs_dtV!Vmc8x5qo+s2TYHDfyTZjZ33=!yU)}V#2!A;``Q#jU0sQAFU&>I!BJ|4AC1PRoO?p+*QQJ1fC(wNe=FhwoB9K!YlVIiyWsi zTI_*4HKhZBjVa1d1Bz8Zaz zOQ)~eSLw7Be5V2H^<}4muc;?Lqd-rhtu%|}lbg|&=|}Y0$l@A4xLu-CUN|=;K(w!i zO}wFd!qjPO*=wxo5iVA8^$}{S(*8-3ba)|o9 zeV6N7=EX07$nsZUt`cHYDf8jk-uA3Q$)|YNAN*uMt-5;?lY_2ySF%uc;%eB|Ch8R# ziPh|afZE+LKdtTAU<}|n?27nJ3lQVgzHFb&)`F}pOIwZsk~D|kIw0d+UrX7R{PYIy zPoA0{SEget<%8mE^o7e1mO+o$-KcnPwZLbA0;vx|$E74(<6^jXBsQL&)bD)Da}r&c z0Pw)sItF3G`de`5gZsmJQ0S)VoZ0I*_r@kwe)30{xc>NK7K~K%KQiX;xJFL*;HjM{ zZ76AuePZ`QC7p+W7K#VDtE2F1XzIDhGM`^pG8Y<}t$NfnW;=ZYcx-rVGRW#L1N81! zsh+Xk4zhcvdEPRWFX{R;vSwg{H)zpRB%s`4kwPuc+M?J(D+1Rdu$TCJs)rT`4&a<~ zW#hQd2@=Syd#Y97Zw@IN06Vv(WDqQkbcq%p7w@_@>>* zf|vIkA5UjpthFKMeZaW+rREgw)w8OuXGIHZX^-+r48>ias;EOGVz+)l9;c`{B@^nq z-ymA7>91Q=E11|;Ec*m=Qd~6RiiB!ra>QT$!7%YfhU-u06dvVk^x2PjJ;^^4zojXNp%80_o`5VMic|m!1|h zA&0 z{A83wTs!{&1Ioj?g3-b9@qfYP5clWApH@83o(kpA>u(NEYzInRpn`b-5JZI8Xj9bR zHae{CxT`Q>OtwRE9?f1wl_Ij8n<*UkQc^%t$wP7n`aywFMzacwCa0nH5ff~MGAq;@ z-o#PwZ<%urdZ*1hpUMbIA>k?g|0)UB8{)S*;-O1u=i|3W>tA5JVU&uyr9mf z=FxoGLx}VG#8iwzmO=T}s(J(NM4$G;dp!(DO&sDs z;dbl#O(IG2$c28kUrfljYl=^urmealj=~bY|1B@PUGi)oN66r~u9gB29A(W~Lqj(S zPUu+rq-T~vJ5;}rizA%#7VH&`k>*uJxgxFMNa)79_A|8X05)7ZA_*%N4%;4sIRzk_q@C)w>>RWNl&xVsSBkCbyL{_n~gWzI7@7g7B9xhsQ zw|xKp(Qb<)%5`X6hyx5DqQHfak7OS(8scSlKz!;{8Pcwr#xjsuhVrcLOU{~aS*4|h z3slt0?k+N=&y}Wu8mx4aBi)H2#Tl^Ryo6?fBVGJhtW77VqB@v=~$6+6G3@}-#YnH;&`d9}? zfuR1;FH{WvxFtO&2ZHS}z5-6NrAIz*eeNRnsAwYs&Wk;RQDRKoBHr?i6yV=Vvf83f$O^{k76=(+4Xf*1rK;(WV3R z6)XPk!z<2Cfp98g{0~y1(7Vgw!apjLqd4B8^G$kR-x~P&WI%nYesum&_cVWMRB-ju zndEl)>=z0vtS-rrq1YLSaob%|$XYhx6j+P=6XXZ(JiOBXV`(dMoKdWjBZK&+ZUcl&0+o4wMxGfNhn$sIB@(D0eac<=;htX?NfZ6{ee**%-}`iPO` zM{mCp*U0(MwltfoJdEw6i_i}3fjO+G#b$Ctz>!?nVmNJHA`<=b<@HMDG2=6D9NI9f z*U@`hb41W_Ob&Qbmi}zL(vcs;(iAyhr1J%)>PGok$R4K)OHaN%@GNjX@hfW-C34&K zQA#{ppLBEXQx___oB>)tf?ICCb@!R^Ysjn5$jsUD&@Yl|7|-ATRy8%VE9v@(50A4n zN?7(_$ZFyNyv5arbQ<#mO&Yt^0Chpg$pThH)WKyi_>~yP@%hW(yg+g?F#(Vaqmp8J zHb~^q4fmj4by@{irFPQf7h>*xw(~?ejwFQdwY?ZBe6G`|Nwn?5&K7HaEs|GON!U|M z{-0&=A&Pn5221?~K-;4|zED5XDf5$AXpjLVW+?9M@cwR3B3Iox&eh9ljyAQBPt@RD zUciM2Rv)Zm`hr?)bPfHUc|h4Fo+itdz0xh8f5D!w3HVyV8Rt9miPsg{12FNmBK84d zrTUSKM@IF5%WJy&wKn;}>WQ>2aeD%JWePVz3R@Ll&M*-2#4GenF=`^YYF)0|fhZS@ zCQ|Epu|8Y4uAC)-pbYL7R_eYd!x^`Vo59Bb00WZ&o*QWp-vAR<{oB1jjVEMD-5>w~ zE5lP~o8Tv@>5sn4IY?_2J>22*eSPp&<;V9~4a?uHYc{tEtd^`~zT3Hy5@^G%5{W48 zaMMv}mle8x^-400A5;K1sr7!3K=EbOGI<}f_aLyX`sYh#mzIkSE)*oFM&Ym8+jq6f z_=hL=b>lGyd15Y9O5VTp+W+2g&31*wAEj|9mjt6_e5wGyAf(<Z+u{}N|C=uW)4Y~L6FmZsnTa|UNwichSUw`J zL2kLeIpz)DHiwhmPtx4=P!E|QC|NmVEEer1Le@_5@ODBHQ0Y=}ZvNdA3$S`_t>Wm=d?GB*ugL=+q&W=ghNDbH2F8C8&?17T2@`hE!Hx0Yx#M-G z?-^MrSS(;uUTS&#&JB%q&mgV*>?^vAeA{4q=!h=GuK^8T5^goC%wl&?)fYueU}kz& z2c1NO-GEm3gKr)S&UwV^ICBA*vL=8Sh?G3%5!H;G2bNjq7bH zG?*eF%oI%wsUq?z-bUN@IZkA3((80Cpxx63PPHWT2h}#cFG+pa6B9|5EnGxxj{WaI z!3Nl*@M{_*T$H$bz@B+?iH9%Ea*iL~5&r7==CFd`^v6!(UjqpYr-VFl(esR(>NX<|3Q8_77Z^Mml!Q+ zJAoWr=D*TIgf@B;dSeG4(n|1YFFPh}wjux;bS2B7MkyM5mlyf8bjUC^7)Ot3 zy(~=Y|D(OI@xVdWz#k*x6JoO;7@|lgETfj7$5UA*vdbQm?Mg*68#zjS5d|-T+CG$Y zTC5m?5audc@yipHvhq0qX+W00&Ki(l`H1|PpQzDH0Yzmnk-H3FU^M0w%J+d)l`Y`< zfFtdD3V43L)+(WEOWEsZt4sKEl{!pGavRZhTDVG3^L)eJO-)v-T?6QRuVbD$2}6#_ zYmlx(I^+tX9bG4GW-8;ka%=9Yn1>0aqmD*qt)Koy*_E882!4*iV#EUCUJ;;=7U@kE zKh?nbY{>$r{AoF(AHV?e!VzS@0rn zC3=e@Ur09<27>w5CAB~;>V#DY&8Q%iKK{JOOMMe$l$rA>evNurB)Bz>-4=F{f!Y%_ zs^q%=xnLIbig}iMY-mz1An$a?#IjO?x(aV-kXY$J-j^koTbdZf*8haf4dK#6Vq;nf zkaXvFrk-+WYs4S*0B5g4*eG{?oRB~3yCoGHXApLHdlLA1hPjwxo__2?eFwe#dKWD> z&%d~P$8qqnhO@FG&k1 za}nG>q^pE$kRN;pu643;#8lIwQCF77L&D5gS~DXRGN`xNa<^=L=*tr9JA8@3T5udd zyuORXERoHBZE0C1%oMk1VzXm49@;SK^hKHX`WKW6uS;vf5Ev)qntnSJc6%NIAfqGK-BC zvBwRk2XnQPY@SJQodB^xm);!A)}RBGZrcP%;UPHo{Px8Pd4+<)gX$%w^D{9c^}G&*!qomt2wK-*^WB$IC2_$^aI{B$#SKGu6F`p?}MXqu=Ut z`)z{-eT%JFOg>dBvCu^d3ftG&6g$Wb>}^G-*K}ZwN&khel?q)?_%va<{eOG}`;{?c z2yK2WmBXfkrHRdYoB;FB27HZmr=-~FEpc;_(leyw+3M2t0MzA2D(x-fBKeP4rPdSN zxnCnD-&9cZPdYuYovU`)h4>L+6fv}=J{1K4|IC{BpaVRkKIclSi($Nf*w z3c)PvJKI=ypOX;{auX09^XNllJ$G6K?s^UHq@bOaTzkk$WD!j4eN00jV8EXd{xKzqjOsv8~z)yqnnwoyd#InZV$tWIdu|V}Bd+c;u(* z6HPi}my1+{UIv<&0O!^>=t&5R_XxS9N`Xg!l+tbw3K$cM>v3BMgoCTl#*^!Y*rTbXp8yIdws$bqTqh`}U8US@t89T?+B>@(IYj5NbqgGRFDUFF_KH2X)Ts`DcUhreAyB zG40G9%hc^A{J;KRrV;tIPQ%8a(|N4;TIm12x+vJJp&v@;&4UH$1$V zITw~PPwAWGOBH#eaY9(Uv{P7C(@l0_byCT$1?TuJ7uVk0B3rHHK}kVh$R?6oU;fjA z?#Th^vbfj3wOjRYqh9IpJ;Y+bysf8Cvi1e|+(`0$R%WB%c8Vu^)fYyCb}O;`XGL1*OW{1Pt~DJ?}f?-ST$%OXBOR%;>g>H<1gK&k&3=HZtU>3 z$WNo2uEAS96RuETcTYE+(j>?!nKK9uqSJ50xMjV5!}+FW2Vgb7tA!)Zv|-m87GIH& zr}I*#&-;-x`$Ifr1~ELywhRkNw>zDkzwmz%K$P3d?HW;`>l#+xz38` z0Hf6x7D?m)k$>!+gDZ10gMUhv6cS!Z{xJXC?L3pJ42Igw9M^ciruvI%S_39QH(`Eg zZb4C3qOHgCbiMnUqkM#89=CU)$&&z#vmP#QO8hinm+PeQuw-Z{gD5m^ymyG1rj4)? zf`D+cp_k4&*ATu zU1(T?g7XVZaOee2?<3`fZbs})S~Ny-viwBc-`j6xU%zw(1WFV&vNhu{iKxUWzzyIL zWfyF6PaEH-=FUW+=AGg{bQ6^twV!%T6!s#HudaX`stz&Ot}~FT$1>3kYrI#m*-4_H z86xS){OJ)C`$hCePwQNBbR{}UiCW)Wiyp4k@1h`#u#mOfuhz8Hs z)(*&;+SpjaTbtm4>}o3v!-Ux;ZMB`Yk6kN+T?4?8Jb`Me8tf0=>65MVGg+=Gw}EFY zLhaY58II*u_2Ar_FCFJg!1x7Tz0zH!Q`zRD0%GJvNNo;Oq7pN#@?Bg{ll^;dl9cc4 z_!4B88W~I)FAhNa5!8X(Urh|n#j>vb6&IRgSizv@Ils*VD%k%Pmd@i|wc}1W+BUjZ zBWP1}8(_^qQ7Ai19|vWf$m)e6Y3;QAra6k#>)W8X?g6%@@Jv9L_CDQ^s~zXfAgc=h z8nksRkzn!o>*;R`1k;WL+a%U{z`U!pLUNwG+x~Yf>!*#_g)fMjG-D0k2GvN&oRUo- zto^)^UW@S=8^mYE$N)JNWfS^$&5gICJOdG;ZJjk{)GRt6M<0;dO{wGVH(dR&R?U2I zEljueKznX#r9|~w8vH}9im@N?0RdB4%SDk2XnKCAvRP%ot$J*wjlW;FB#eX?9-BSf zaZxZBd~n<)?OwKHr}GJmiWp}65Sc`l7k0TYGj`fjm_<33NBlNzI<@a{DckL$idx#vTV0RgrMb4VyW>guZoaqr?nI_eKAnS=fj$ZI5rz zVd7+GLW!&18I5fHkw#7$300V6@4(ZpXR>j6IDOIGUH$#b=r$N0{KQ)uKFdqDip_a} z#t6XtwRMRUSM+ye8YX6LLw_HRa7{Y zY$-c7r4P}Ani8tt4aAUG0l0?ACji#{>~}_ct0n&MQtknm%sGzlgm=0+nV%SvxZHu_ zKx%EA2hcccrnWR0#eI<1}?Yj({M!Yw3y-a|}m4LPHPI}rLJ#`1n#J(VV`w*h`x z<8C9)jKBb~`UmfLG$*z4{RK-h4v>t7NGE}(hht*xb<$CLT#1T6t+>6kyB>L#hhEU! zi`kbQ3_8%7#-Lk)kE_CbTbv0c(>H!)2DW$Y83wl}@NdJ?2=V3p{)vH+j>;D#QFV(b z>aC+ezAl?N&-}$})#*L!NCqk_NGr#@G7Y z>OG0gB1%v0x)OPR^WBfvrJhVCKd{Ff%U%(c!u(8B*m+vXcR%Ns-t8qsZ0xn4|&hJu?rkEh1bgyHFEMzOYlEEk0 zeX1RnNS2Sk+>Any<8tx0x!$~N_<6Kd<*2~Oq_(m$VTe>vLB*+|+mvi#2ln>d{ z33H~XqOY1VBL#Z`n<8dL+9xX_sA|f>RVwxL2WRl$jbp3}!{az&0s;5NsMV7G^P3iL$_)Sl)gu+NLN)FgOidr6|{{|(7s8u^YIq+l=y2vu6hcZM4 z;K;xdeerh49*tIV#t0>fF{uyE!vv0@S21C+h(upJFp3vi@->p(qTytuBg^)yYu<35 z^j3hz#+3V45c3(biR)+X_gtS(vC$^eKAseX=%DR zm~jIy_w2m$#+>p_=Sroq`%}S5gD_vPtCI0&Hm(Uk`lbnp;7W@m?bQ%kbi*Y5nCi}h zkSz4zlMx{OzOeaYeU+kAgawA?GDCp^>qkTn0}`dK&1trYK{LrW^3Pn@VsA5f$OMjNOj zT~fYS=fZXCe;0sAS^IXCfO*;^xE?zG9U3d^udMxo;sh=trlMkp*L1$+%@?v`8 z(5C^(uOi~$e&6^UNv5_H_5WItYOgQNhkT7 zr)johTDI=vw)b~MRcg@2tP6u6Ch`>c-|^rdRcYUy7!E#2_&l`{I@;@@^*#O$aB>!d zo|&&3hmKC(dSS+70FWwt$i%hD>^ushJSh9tSWaGJjhI_gw^0YEk#ym6N$Zt0GHRJ* zy#p)OH$8@r>;J@lWg)VK2yS9CTZ8I_A8+>`crl=aZ>uTPy=m?U>Fbyh@nV9!il`u| z?}82G-26J9zQ<*W)mHBICGBnm(331Pn}9z7^&#&b!>nd2X@Bfgd-04HDX*pC)N#`G zkum-dUF!9^>1u_Ytb3{T6Qle*$A920^rXc(5dCirz%N&~nX>{1sQndqd;#}WNQJIo zx|%zYYgq-6qT=Si_Az9teW0a6JOGz=7axs&0}i)^p=n%ZYzr{ml(=8`J&Qr2hhB)& zJo0|xdXPvsnORmUDZ-Ooo!b}5*|k{Wd`>x1tnoD3mKi6d?NUH#zbBmGY_y!{h9A}H z9IALCk3XGF;tS$!)o8l`2>3u^uOOQlgq0quTVhYMJg9k&wx)7r<+ZJqlvAAd;d*%; zriwHxTl}9FpRGLzi>^nhxvV}~k0jwY%_gJnj-?-REt+t4BINPBZ`+i*Gno*;`{k4^ zf*sm?QTzyWdI_xC%(ly=K}Tnrv=eJIgM6!m7D2$7?gX(VD07bl?6yIg^QQ^W?u-w( z$$a)=U&-b!?fF~9Njz0#?9zAX7zo$T$JN6* zJS!+|54$LGWEG)4&`Q*QDm|)kpf&ofQ2Ln>XffwwIvQsARVZtZE`B7C`c^Bo9pm=Z z9?jBmPWKZBO6bNvW$yIu&l)eR?p|ROH39cHd?~_DJ-cCcK7lPbv0zFF62X_n*4Gjc zL_{y5zf|fAo~yUvPXovoo@f1{b2lsdD>ddEVf9RP`my`ge`V0b479mj599`W>H~6` z&lyXb?zW+s|mQU$-(m$x+u%{}8bUMZzmY#nLGZK{5Ki)R!fYN{G_{34#l;nSpX5fQ*qiOOB; z@_pG=6vhY5c(ZA;Sx4mVeeuiq?}m0I+0?sMRV$tgqN8vE7&;MP?5#_`l%|k{lRBUF zl939YK0b6?Wc2Yb;0|o+&zT{q2#!K_whsRo{jwfiSo2vcz?l+LYS#VFZ+VgqQ2wM-YT9Cw|bZPfB;ll zUg8(>Jj!fNkH>Z$Gk|xcET6KkV=>#7D%~?NU8<{7=y)bEZxtDddgVNJG|7XhKJ%8z zge4lH6G1N(0*K5^iZuBZ#{8pL>V7;y>3rDv&0Wk}9x&}pi!>QWFkz<`Ug)eSC*^v& z+5pnop75&mp%)lSy3;a;T2Vz0BMa zMob9Z5I|%*^3G>Tj7!5eP)Cs;9I{u?lyVjg?oRi}I~CcAs`~P)0$>CtJQszkO#|gL zHMN<3R;fKW|FpqHqGy;D7TL6NiXnFG^~VS>w|kf?HTe2b&fWyyuZQ7bYr0M5V49`% zJ)Yevj~@mk`W-Kx5lnzS-BGDm{06~>A7$Ye`6f6r65+np|Fq4OB9M}}DEbbd_?gzB zG5WHxxqk=X^dF0h)`Y5*8!_A|gc(@6N%cP*s^wE~1VNY1HTx8l{(keEPydXh%TkF( zr6rg($vRiuo?_Gavs4tc{(w8ipQ2{XOVyWv#ZRx7wz^aT_&p;CSr*xd5dk?j<;HaEn8q}VzT z!n_g#EKky|4&Y3@I7=oy@tT1~ZN2f~`hskUn|wS@wOE5Ue<~c2{f-8VF;*Z}aj&-N zzj>#$spXo|1VMHb%o)r|w!rK+P+x{YW!P>e?8-+VueHu&eI8|EqI~!DXv{O(T!~_2 z!m5d=&%5QeE-TEM^VL1-)Ra-#xiU$~reb*$JxCK}g&ne*#^oEjzPE!0L51iUKthSZ z-tiht>iFA3i1PAZ+fTk(8<=AAif+0%Z;j|Fq)gzk6kK5AZR{DhNN`Amd8@jbN4o$U zpd^8VdwrBkA@d2CT&p5-Eu%qCsj~EzQ1ozWlhPI8>T?bzX^?9g#bmcV_Pc6n*o2TW z@!0Ac+dz_~2>`|UgFmCJ3k6GTR>TEN0vea^?Fg&VUs(O4YRmzL(=EBhp>3EeTPpWV zH$$!Z#j#AC%0reBUFEui_MxD!<;o>5N!QvF+*l+CGIq6+O$Okdm4Wia1wCdsXYC0| zxDLrw&^$!fWd%nzr)^C04Ph9TVqHnjU&MA@a=Y!?oJ42hc1W1PlAH}SPxzV-)uWVh zxps%+g5s^Qnww$SRm1Fp7lK0MOak+$3Z+J^Icj-A|M*NiNq$XsG*VU+*1uec#Yj$W z2IK-yd3n?Kw@a-tihIC4ojUeG3#W4r#xQWoNd^;4`*8PH6Hf%CHmGmMM3TF3)UnZ; zJ(R`t#>%8ZO|AzNs6OH$N$OFDc}+j0(Re&XvqRcFg&H!y_b_!+)vtKiImU)K`pTc- zCi}!#P$Qr1s>0tU^+H6p(OFrkdt!mCe_*~|xk(lGMFGYBdkvy-%@XqiA*MjwZ{k15 zybLc<7G<$b-VDzKn=#Z+0d1F0pZ5gBZPv-_mh$(RI}d&&hx&?@7?5-evlpn5Q1LR=gC9m3w{mQXhLSZ zG+DdVdvXoDD@Kbp{d1Yh{v&3B$cZvXj%W@`%I}8=LT_s)sn30a9Rsw`Z6~Oa%M{Np zTyHLLb=wxa_0eidhYD48z z@<<&Turied{{bO>+eT+UL)Y9TkoEa%=rjmIVdYeBsqk}>(p5>i-M>;|&pNKIAD&SB zcx949=bNHjj&TLHc?(EBWYgI_gT=hq!WCw9`T|N zxxj1Ijq?kk`8;-u2jx%_&9z(#S6G`m!*ibgyG&9}1^Xr1u8L;E2w1yUKxsqb-#&Hf z_1RrNd}|EwQpdkLByh*0Bd6v0YqvV)7O?nZ8V40)Sm^R|%3|`4vH;7nBp}yMM}8zBPxO<47s&naGkVTo$*bJpw&J|9cjBXzL;Nx6Q!X zjSbYgKaRNbbo`sNTt)iAW1C91Jr7Rj-5j<`Ehi=@i|hJKuI!t=`y$MFAR-(l_J~>@ zicMs)h#dt+PyTVn_$T3?T(t_>c!*V-7rN6>@4;@m02PIb75?Ycirqj%p||=tz=PX4 z4`O}0_!Qd*xeeJniL%0FbLkLnD|Oq~9ujsiR%K;>n%%P`mgt|DdkO`d+~;)Sul}xV ztNB0re2dVlgc&Tr8S08Su!MLwm(RzSjl#$HoHgbC$g%7P4~eJRFGDX=zdF7=l}7``9# zZ^m1k{S#e~rB|9O%GWR$RH7Rh?PyYLHMLGyF$x&PlVDCLT*N+7bv+U?vD;@IxikZP zDPvfra-d=$u1tk1#T>}^m+|ffOjJ?|K#FLE&3}vaJ+lZ#kRxLH66)rDR2-j(0cS5r zfGRcUU$$W;FZOSsq>YwJe^!&*-KYCV&YOs^3J(~LKYL0G`3*q0aVL&Vo1KE2@0CRc z!>eaqe0&tQbEZO{9Jm!AoDUF-qsuBh6Px$sSJKxe7i>l?C7<67kv;W)ORkUnUJ+fg zJ^(Y}3tGL;elu!duBc}4P@&dmT5NuvLfmX;PC!Og6^nJ$Of>{sN%E%z4VrakE>MV- z8};N-|Iz{u$HMmY`07Faw%CB`W@EAA0#UNM{Z$BxFJ2E=Ndt0Kg71HXegBPTNX(e- zr=!HrEy0tcvY&~RLmeG6F~h-89=_^A3GhWkb)bh2NN?AhCw-A}bv03@8j_1OosnKI z#y_5{&GpPt&~ErT21*s93JKdlW%|~$!7S)zk~lH8wjcXLYR2g;X^E*z1fYKmaqzNE z+```tn#q@nx0I}sfa!{;YBDE7kDa?^mV+6U3P-Ea14{a(eLzSbN|mZX+{(+Sy_=Rd zCV%A}W}u`_=52hE#am1lxPr-bQ?!~^?SzNZsd;+r_NOVJ}_^wMDAsF9Kx`z1TXPdRm9dhQ> zpZoKL9_O3&oED)XtY|S6HH@2HjgCpW+CAJTQ6%IQl+MuW^HEd&git)43S1*6I~?s3 zBNe=>KJ_&1TH^t8{7h&@Fsi;$`II|LDsq}BtIJRtN{@!W>u@B&763Q`?FiGFiWB4j zX7Vjvkehao5L6B#l-I6+xvSyOB5*C2{(P^$WJxfOHee-`Q@XQ@Jy!9|mkFLLYX2{C zQNQ)hQ<)SwqK|+ag?X6;=S74y{KyD7k-kW!UL@Y3r{3fdt{)ezV?r*4Rapz#mt=j< zCGM>%ogxNtlq!g+jLS7axSTxUTtu#`D}&fbMI?`8jC;9RZKQ$7tRc)0CHFo?$XE+v zF>TktMZOD?XZz!>6FBGK?_SGK&CM3@`|ns8ngcB<__1_dmA&zKeDM7UIao(oF@z^hHWmj<-mj6`9H$n1o<7eK zc=nYq;C^wzb3;T%p4C7Db|OJFM*)0*+hbc@RURL!cgI6ND`|sl)YC;UXqG1LTc2rP z@!DQFi*fRdVTFG9bP@)3Zl{{3sv{?4-g({>6SSN>{~@}xh`JH0r4f-xL8l+wjGnps z2s2G=Jf)LmoV||da2EoEMumZD7?x^}=a6=kET*<3@UHypP9w<0gxDcyV1BEd#N3Vt zDxCh<$d(6F)z=-x$=8}qAZ0@HRPd_>#Ae-NOQ)uKM(eIVGV|1MJR9rpVO-MF2wKwp zqZi~ZmOHGW-^|`LxyA z4e@WIU?`%muiX&gS%FKYd}X`xHQt&D;U$k-jTeVMN8r|j+$j+;Dg_#nbPsC=X1Lsa+>;N_tM4ak}0)^E!!!IO>urWH&vizsbSJUgW zOuzU#A8l-^cwb@sqPv!{>u0wo{$>BL;g39-Q;X-Q6xZQ#H!T=(aHzX=GH{E)X|&lo8+TROb6VpGG~04&l1>h^Qck8ve}h44`*oc^!} zI_05z@DG>mXP{K#lyzUm%iHW{7XuNT;RhDF$_VOOb^@1D*sfsd4}?_F{hn2?l>vq# zTHSmMl&#KpSW_q(#RxC8nvQYZI$QD=X7SL6$xB9_HXL?)C_5Ji)kygOTIThAXn_KN zv{G%%-8RSNmvI3E`Lb~cMv#C`(9{Q`KVNeK*FXMCAf93n9tn$#nV`1CIvhV=u9AXs z-jBH9Lt-9wI@e5K}V- zhF9nA5<#c74>q7gd0O1H{5h4e-;a~pt5GX9F1r^LyKk1uRl`vA^vAiG#}6Uxu3OVB zxv$HBK%OyHLOfjWAhYv>5i8Y{9PqrKKOa;act&i)O2DcqA<8g~)-I!2My>pYec03H z^F$n_Ra@~!fv5>If(9($+*3omVJdUP_+tBI9>RF*0AwFG2pEe7g0N*D-|m3PZdM3Y zm#31A-+H^3sF8Lxd9dZQQX<)4Ut55)_N6zNefW43xz?iY;&pY0-0HvZ)m^V>#wFK& zVG!_=g>!OpLWdm%dG&W>DCMS{CAT~}ywprBl5ThmIqcZeUfInrYWKU$Z>#14jB%l! zdP@4sw%U4+{a_8f2%4(e6^0-@auO7gk>1SI8w){x`}9=Gkx2#RwNc`3nZ{}F*u5kR zE+>Os)HDPP&8!*ErFTocSiU3Pnz^c>yJG8O1ESGIr2fA`e+iUrr1c+DjdO}1q4gO) z@1lYpBYESTAF-M;Fq0v1nIpW>9m~nXic+=otKw+IhPnGU?LsxPNUurhNKZ};Bi1L? zy~s#`NLTraHcq4{#eOx&2gbf5a6HH>67cJ?$o3|sqVKpZhvjGc-BI|(s3mF!UXD~x z6uwPZ9?NV?1D7{BArYhgNl!mABa8*SynR|;}bZ8 zZ-__EU09&*#ZvRnepwos z>`s(~s7!6LwQXy@XutzLA+$zURIEqdPNJ@=1Q+5xQ&2x6uSN~Vv#WZjn!mh;=jxE% z@jv_*T^7cL#Vd}r?&6d##bFru460iUIKn%L7bEv z*V-O_lyZyP10Zw|1Sv_KVF=r-Aqy%>(;V}kE}-_ssGb3Vx72edu$E@O=3Q4209FUF zi9S>s4Hm*mtq@?{#o(L;Uii}cU}fTY9Ump{LN~3!9PUJ4Rg8Z+C9M>Z*fDgok~(k< zqEZa2$z~5b64uJx*!=gL7|JQ`Tc6bq?g9EbQq*dKE&`0017gs*H0d-2m1ld{AEeF# z{ZP8b(NrVi99a|ROr~r6PHkyYiOzgyIZ6ykjC{Zi$m4CM^j(`CgwT%;KN^_5-};Wj zt!NYyTCG?&;#w_Q930pv>P^qV>xIf`jduxqqvpcO>40NL4w2|MDi9$4b={2L24_V( z;EX-;*MbW!`2r0)Dg2S@f+rRZRbymHQr~Qn<9hC!dE>+@Rrjrsi|}{KUFU|k=v6?5 z9!WnCGh`T{JV|uu6@PB^_SgHFD6dfTky@uy&EvTspinO0Vg&MgT?TYr+O?rtjJ7^= zXp2B=eK7_jWZlaHVz*{z$O$@=*(AYHlOUdD*m3newy6gnQf#n+4j@1DhWz`AoR!BI zu`2wm40$i=xl4IJX}kC;Q=R%)LDX*SkKmA(O^pKI$tEXLOwiRHxw7EELi{9U!_%2S zSZj>6fvuaeu3y%<211@Q&fb7Pz^v=Ip40&`b#rqTVcY#-J~(kzelnBIApn0JZYqi>|=XHj5)!8eYkW~y9vNtoDb*e}1;4+`jrXkISJGo5QU{Mk2z#QV&l z5$O9wF;u38J*THm5E)ZTsN;h>L3Xw9w;~pymic26f0Infmyl(>Ic~M;rTl|Cw^TemP_D#9N+^1en)lLwTe^lExnu2>R+vYXV z`k2Q;QMo4iE1G{1Vic1}q>Z^XH=AvpJ?*AV4~J#C7+odu!M=oF0OAx8TC`7(-ue

h!+;cV{-F&{&1LE$h*91=;-Zs}q#Bj-Lc~xE!BV7QH1%oaCK5 z`RW4!hWpKxs0sC!+Cs>5buqdAV0~|p=>`=>9bu$>+EV1xa*Tiht_7bh_wMlOGCqDTzYAP5#td!=Fi_j0%EVIJD^+O|}1IPXf zO}iZK`c~#o8y@2ZRPKe6F}N-&9v8cHb@(b>xGtUaeL`)uex<(FHZEOZSxmj39%=zJ6QLM z3TD4O6RLrH@(kcX%}WD=d0v~-{`g#KCLBfjIeW5-nyR9$XlV6+ePXjgopaFKf*LxM zQ+ew(QNY9KXC5b#v9}Y(Uyrdaoeil`es>h$Q)pSc%wGR;Sj>K^H1wyDi&?b%YjL=CQf)1B|_xjn|cQJ__R7y#3h*jR?KRdNuNU6x;+^8TUqfH zu)b*tl6_QnG<%e1kdCEeN%Umr;>6vbg{8Q)nm48y5A}x;xwzVWX$2ChD$E zyGpB-FF>O&$q^?=4}wjjk_7;+ARX`EZtdp;7)s@+c|SWDrat6b!3erZ)p1LqYOyk< z$SKo=h4vBM1-{bA4Gdi1{&nwVni>5#;*}eFIG?xqe1I?R<5gW-dmmYW=!O>~&1L|s z#Fyfh?N#g-lKaFti=3xm)qLn-A2Q6Oh)#%Ak$T2puuJTPrTEMZja^)iipg&Boo5pd zm1}UjBeacifnq*HW1EhfV*-aJl=KwbsrAn{kkZ;`=uoB)c;cG*Xsi%rj`?KEaH$)F zB#9!%J5AfgKXg@BqPt4P1(kFW6ium->9dyThFeqH3say-H>7TJ;{7w}JLikdT%uH? zg+lb&s9Osnel!3pshXL{>^s~gVS8lACkXtTBz$k=b{XwFrx^qtINU|96=wx$}- zX{?+aqowZX%u#0I>+lwGIjQCz`zqO1p2tVgHLysD)yC^-0}h3JIAxMz%;P5EoCUak z8&%$V(yt}up+mK|1Y=5grRF-wP34IXDruEu=&hXMYHDoK+zH6bg#~4^vnpMhK_0Uc zlAByKs{pg9K062*n98qGK~fiCp^aGLtcM)XQ_dV@)J-+zkA=A^IRaS%J*tGvjgD6` zfB^oc!=9gux9~ei1eyz#+DTXEsra5b?_Wr8D#!YUaEjr3u*F9BFhHw*c-Ghsd=nHu z$X=cwCvGtQbpK$f;=oLJe=G_UFqgxs*3CoiE0)S-v~nu)RSE>IA(g6O*2~9q7x`V*`p3>eVw7wRo?}v{s}##vrkh0 zTlwvc=*Wu6Mo$K%I&E%6r4O9tz~b{ijq|iM_3O9kldt}8Uo`vMWz+3p&tEy>M-h~P#Z~jm5 zET7uA-?L_-NCrJvSP*|LK;;}kPVX~9`HZurc;@jk^%<{R}>m#lfPx^jYQ+yl5*3o5q)82 z(r$05etwKo6kQ8&V5yk^(A_y`4Y_iFWGkh>NVh5=g zz{nMU_5R+;ABSb|y(?{(d=ERy^M*AQx@MOVJ{e+McNP>Mnv<13CGQp6h?H_ z<&OQygVGg`PP^$zHxJ^ls>M-MudkrF`|p7V>0$<)jV`f!w({_A>WR%2IpreE-@aUy zwB>@DA8Cb|XNe;+V0{Xb5Xfth6j0SD`RG$^0Qoz}f2~e`5@1e&J0Y}-$Kf;!Zxf!c zu$|Qf1|G!=xZTbM-B{+tw&Ad1r()GUwbq%Gd3-S-0s$3k40yrXW>Mn(4VHA1IWK2w zYa9Ro0@FdBAY_z8Ts!{&1<&aiH-h`S)7u!`h_6o*PX`7v ztH3_44yNo)CXc{CP~7}J|3^MTKN>!8MP6~Jvy;};7^m%>ajyAzN~+kh)#X~)UkqQi zc)H55(1sF&DWk`qj_8x~9zJdU1!y$CzsmCbhbjaYbw|SB3ut8(!hg+W2sfTcGHaA=(9g0}jHS4AiJ7H5%tI&7w*eFdF6%QM88&c+kjS?u! zb!^!1tKGW2M}I*rDy?b)4mXKyRwg}zumZ6P_$*`jf6?&p$fb(7Vo|(%>gWCA&Qe&g zIrCkRF@#`if%*=NPq=2xWT#KqsyNR>oicgsZh5KQb;sgM({{wl|R@t zFI3l(JdBKc2tQn-q+tkjY~;#ypvRs?IX606T;XYKEGWhx4X)m*1ZYyIkNKP2SCb;K zhXtax{D0BGg`KA#dQq{@XsfV{?2279SRKG*0Vq`sE{Z%3YsrPIzI)E!NAG7Grx;>1 z{4h|Vta{=$vh7VpYGR)X!P{oolnh?tVJAbts6`k8(9Jfs>GbC1>Cz-2M2>#b07pqc z7xz8fA7+?buEr$zL?!E#tONqeUWy{z$r9=1`9BIF2%`xn+BK-5t|?POo;>dW>U`>r zf&mt1qm$E^c*yDvW*APjKwJlO%r;;s)eg;pC}|GbeelyJCV)4PQyQ@W^u#9u-c9$% zT)3jHnXMMt)_(PJ-`Oxk6Uca&%`{BR5-XQ@zLQMN6bO<#z4N2nPM93b2I>xNQQOJF z4*&oHB>|paX%OE40(;nWws0Fj@Om7L?qbQ^imYZ=?Vp*c;$ZpZleo zxs8EU^S0Uel9r*+fNUp#3r?akQ%)13yLy=M*6XSk?y3|738GnGBS!5awv7mCAKnYB|Dq+(=U0*SFr zkj$U(e8x2F#(d#b;|Fp^IneKO(c)1_ZhH>>r-!Lqfx8&@TDFhMxhgZuL?Gngj?AIr zLvM3LU1w}RpMI2+op%Yu>KZ8lC*(nBjo=z+ELAgyCf!6LCce%YHIB(VPr<>(3#aSh zT5PRSu1t~2Dvpu$TJ*S{{0Dfn;+fHkbmuCc(bDx5ns-_WM*mY^@TH_Z@qXA@aXUHB z?}1FAk%8txj&r|-JaujBTIX`N^`f!(nlt}5nSn>>#r12z(;zd3X< z6pFX%z8CwfF6*ii8Uix@tqpQVC5r0ke#Vi@01d~?LBIe20|Wt{L2g5T01FVl2EW(< z1=IX{ECe++*o#NsFOxR_q zh)|ILHu*^^E{1NAZI1ABs5bP>L`EQi$sgapf0X&$;Tot=k>zz<6J=iX*YLB$a-Vc8 zs85m3JLY5i5&F*ohB`+kdjG#ia`}FUAKOKT!T^%Z1R6s$U@ZudtyphODDD3fNwQ|P zOeHZ}(Q|WxAY43RN2qWZMXrB47CnT~;7Cn`koXml0{J23npO-%V77gl+D8OiJRQEg zT)HJ|jB&MOQI=)}6bL-&IV4=^H@iYne?O(REVr|76z<)aOmKcyk|LFnu}`3I@2#Wz zkGF?^8$bWcf4O7r19F=+t1i>Xa8`A{4wnWZyz(Qge&{qIS}=oe=XK&w0V@$_AJ;0^ zk_)82zm9~VP|;er{TntNvW8?{(XtucY5BebcxpqPYD5}oD*%SUqT9|whg;rvewveR zqi`<|4@54`?$}~dEkw|Td;q+x$-T=WC1@7eyz6xg3^KMSQQrJ7;#ew$E0P%dyKK^0 zdYU2F1jRTXe6l zBYf=Z%si+H{u?b3Q!4aXZNi)}*-y$-$>KfbUJkUhonn%tNA&NL)kG_Thj$rYYlnD9 zKu0OFiULdw)q zF1ebMea446Cf5TK3hkFyX4ap={j(n|4vev#W&2`ey}kTYgGN~w?GwX^X9Tm(C8%)W zk-rq31ifZ$^V@<34fSnhZbMQfhX-v6M(f&g;Oh7vaibe5t1%P6l_Pk0aoT%yd3nAT z-$cwqFQFB+K_wc@ltgt4AyFUU{6LA0lAX`D2L^TL4sWO-fcq9M*){L+O z0m-NUeJI_rTyCw?Gq?!u0`aEuwLzT5Wn@W+wsR5KC5M9E`fO}3-yM=!6{d)utd%AO zVK{Su1y+BVYRnA9*`ziDQe3HUL4>K2P&uF@oip8rnni0lzXdu1ldFb$M&h$y`cp)J zNdkzO)ZMig>?hf(usD-!^kfg*bM&(lGvw2GwUtB zB#DICf^|mgJ_=}08RRGj<=nRX8cmD_2sS8vgueicX>*O?%jXI*c-~3~dv;RMr!A4r zl9~oYBE1>;OVXWWEcYf@l}Xw^F)a*{!=K=z<%hldPRP==89G3$AI%>dg0KagAbjhk4I0mg|Cy*?k-p-UB|4Se9#L^kaN7TTw|8sSIJesta*cQ zPlXcAkaW{&TBht#%n^YF{}?|uQ6zZkwkzfgqo0O2Nt+Ai_;3RSYdmJXx(e*L^Z>?2 z2yngP%;ofo>NB!#+L7fZk+K=%(X2R}sEE}cHRW)I=9CWHktqn$*T7N8bW^>#;C*sp zdz`D~p)blnMU&QhUy{>!`}yYl&d*0m!vyx|CXZpLOIwe=ZfJfI3anPAlg=>RK=B&F4p`azG48*j=C$B=!!Q^Loi7-iQOb;I-_-2px$TEc2~&T>6w~YY&>r5gOeO6M}jz+zvq3N(wTB(PJ!@U(G2sCsNmLCbS9TASP~LK2V$on{7E$`<{G^ zkXlD@X;0FQZ5sZzcE2tGY^DF!SMbtUF{uE}nic!!0qhHv%WcUUH1Dy?DcXvctlo)1^xEc&Y@CH- z-6b=B#5uZM_K*gT3c~wqHksMwpd2tTaD2@pFrviYdK8=EkT5{qrAy)6)7;NMOG14( z!pF48=;Nor0ZBJ;zM^^05JwDl=-6qDbrOo8BxL31QoVwqO&s+$!jhke1d4;krCc0K#@uvcv5RU@6mm&UN|ePES`i zFL?JL#8!OKHvlw_!UuJBUXH=fKmd6Tj8Pdv+a46vtq&q&O?lx#q1@3+LVMC~RGD25 z23Ip%k-envjSEA?pb}ZvR1vMH0-*A|$A(Me9_naxHY#z%w(~t|-1We%&}*E5eW=Se z0Md_ABd;!p2nIB>wda;LoBm(vY~K{2%!Dn#?O}G9$NVkD>CRI0+hv)jtOLt>_2ZUN zKr?BP^~VH%>PR4xuc0G!SEM?J=2hn1Av~$MXt`=${8ZJU3pLyuJT-rRH#f@!R9tQt zMLsUjbMSKS1H=%I9@Bw_hu}LjsaNn?VgeEfYF4);}gr>RNx}&v4p& z?N1UkzCGFv*vla!=Da_mY-&XR_(*6#GGb5$u4GRjWklWXF1Rod0T;oEEiq=wX6nHC z8aM~X7>1p0!pa|Y>I^p18g_Ik#6%VZ20;@4ocYkcQQd;?M81`a4^BNA%m-%i+Q@|I zuyADJ=S97b^cZ^tLIcN^jRN|>yKc}^LI%xR$@DG{UU3e2rCG)!c%?gI8SE&Zc}7HA zYHG7`;O2O$c>+E1eWV!a&)921wO6Ld8Q|s7fG8)mhZ1}`olWu%TR4kT`s%svXs3HQ zl;`5z8$=wuFGS4@fZ9xxQG8Q8(hc%Km9~PxvFAX;w z77-vq6oW!4=9_Tlck1`+Mc zNGgnWG21{k7%#U9z7{E`CYl2r{8OGy$^HOT+h@l0-y=z`_48!L(GsrZ(v!@nC)~&A za=dtxo0VvY+O_h+`>B3`b77=viZW6#96E8`m64P z6W!J@ms1wO&B|cvv++c;+0LS92j=z6yW9Eimw60Jj@J(XRhw&&IXy=2!G;~VzuP~7 zYtJ+#vitndBiyHP=>X@*wZ>o)_i;|9XjmYX79|?s6%8i$`#U_qZF9dnDU?j`8E=Bs z)lwGPi;{`QN`{*2{3Gu#)W7AfF|0JMW12K*tiF=eo{mXB9vn8U>c+@M}h_rkc?4#3&4p>gBWs`mVAR}ZEfl%Hyr<8 zKipWVYzhIh3gwadJ-Nm&QP_Ydnd}L8eAvJeCm&NggwWbnOG9!7M@CqO;?{N+)VacP ziH^4vL*m;uiO$U7&-C(56DKS1=^YiJDM#tjIgNm8)yQOkg1d*H&BZj=2x^N%3A)!R zK}TS~h?;E7jAt^^bA96&tv2_fEJSdH++xsik<~N1>?9tA?TW&$87pj6wfSCDG|`hB#;>{fB46V||-4a}r9lBQfIAC#1{yrmT+TIip%$!@xS*fEGL1%77 zuUl-907kuIVLXzo`=f7wIu!rT3wFJHBs8HBP6y~UT+DfHD4XAb)X1N9(uDIa|LaRI z0EAQ3ms=`8qFylep_I{6dK{zhv--Gs7VPH`tSQI$f>zAXEVbq&{-Fno92*vMCb%aj zOwXlMd<6(5gw;fW7;kRdJFFw!0O?pB3m`lOupD^mVP#LYXe&mu=+M8DrQvoMJ6wrO zC?U!*4{X%&0rMpuT&B>xf3kj>y?bK^$OdKDwOPRW#%PC@c;MZZda4J>nONT zNyt~bxuQn!yn3CRrk3EAjMV!EUtGR}^!L9p^C_gT*=DWWzL@`EjBB_wo^5ku9zlXk6sF% zj-IE~M#&4epUYi*!XXA@nVb#x)DA)v8TB#mb~m2rttBX5EoHoA#Dt^GkU2rY-@! zo*ooB3;a?g;Dr>)6@DJWmeB!cIAK14MbK7?&I+mmW z2DNW7a*xo+hFK&r#OSIMrnFQ(+MFi_{U|9;g!kgz)yW8bFveNz?hk0x15;|Q8&<$( zlcIiHN6fZNO@1XjWh`3}<$4r}Cr2w5`pW^xc~25$OOy@|0i9WS<0+4}w9 z?B|vHLH|)tAI4jx`u-#yiGJ7($@#MR1|Vn`)588bH!dve70-NdK()~x`Yn2`sl~W{ z-|e7=`IGhjfx%%*Aq#J?59Q&;fAXFnvL>8#>g?^*qzKI?FMx46G=*BxvTZMyDch%I z+t>fUJLnxtT0LzxG;>OBvz?unXm+td64>+K(?2~Y1y;0mjLBF{jzG^ec>-`rFD&Zt zueY(0yO3OXoGPX4UqkZ~1EL*-E6*nkQsAD=_3v1sii`Eweki)=A^ax=>#7~tV)d?>E zm_;;P0P*H){u04C#DQTiU6X~7n%s^#fB=zm-Tn;xp=-&#m_et}tXO0(_wwr8oQ1J4 zCZ$3c&-56wY#y$?rIZ#QH7g-RfOu2X1jr1BB@a;%sRS1+y-8Zi8VfNwL(Y>P<~9Ai z3g%0pA?45}$;9yimCM~J4JYJfdn^FsE`4K&|PT0KI%wqmI^Ht&N&Z*D^-&YxlsKkASf_ra_% z$-(!jcWoRH&uao%w94m%+0hg(KKTx{3HG(i(Ks4jQRTxnDN$^R_Gf>8OHEGWh(!zy*ui(f2kGd%x&&nDu`f$lQ0`M zq=!tG%WSo0HI;u{!szn!CimROm1HID>DmC32PjoWOJ8^c1+^X+ee_n+L_j9wYI;2$ zEVG7JcyTxz4f3<($N0t~0#R~;?4_mKAoNy<>BC(C)W1As*|J&$v0cobaAc5ZSYyn zmLvTCWO+`~iNVRUL7m3(YT)Gsiq)(5Vc(1x?z6oMFG4?(a+SJVL-9R;B6V%ggTXH8wFr zve^XeNd`$jz^9UE4i^8n&vw|Ec;Up$AQG$qdI?B&A%LV1vIXHY?#Td&nzx~|@mX}o za>$U(ei?-WzI<=LMr*w?Gs<*?x&fbAgPj5Vm1A3Gc!TJJvU}fjJ$&;rlo?*B6Ck31 zEnmVcFdO&J>{U_7S`8)_LuJ04du5r%D zbp6NM#My>FM2N>v#+}@!c%->dvO>Y@`=%y zBCRT#DAAsh%d2W|3bfpbs?B^R(E59SBrgSbIO|Y;UX&yvAT#V4T0M5x>Y{%eWq6;d3R`}Wp z9};(CVh^yoY5OMs6L6n@^OXjh>0{bzzA4xIpb=>cwIct*ao%!tc{fcBH*fs}XWpYr zOrF>49!Af^n+EvBsWTTj{t6G4pGa%$`|^Y&5BDq*MH^|7(4uU=Ygp5D^jYa;ad2=% zBHf7LA)hLB`p1QX-sTqexyCN|qai|RT7;YcE7=4oD)RLSryFga?}%a&i?woVF_~`l zWuLl>j{|g%wb-vP@P^TXsumTpA9l==E%!O(COXxwQlU`F*;vpLmGFxPGm!=$)?M(| zJGyLezsD9rAKHO!PVfF4{M3O-x*e081q>rUN5kZmeglY5S<0G}uIM7{b`|jV>8!y1m_41U`N@5un zEn@&5285ZYamGnaHo^y-)6`|?t!RubO@#2Q(2Bq!<518~Sn?b2AWNq72#aINn`ye% zwzLpMTCCy$h!3SwVG*`ylt41Ar0WSM*nAy7xSJ>&)$LRkQPet5*G6ycKUwU;DmNSU z*`}?&>jU8J(-(z@al~`W*xzG*trf~t+p+4a4wT(Slk^}Rgut}x-QTwEz~5jbzZ`%H zf55hp!Wx3%>=2&mL!Yob2K5v38->MgGivIu*H6Aokf&aBg(h{rGb^zIsUNrTA|~}f z{7N*SDvnCgII#9r3qj?}YUs1S<}X}2L?xHV_tuN|PiYSNPOM)dG0nJ_kZW4&2B`3* za*kcba>!KpGllM~0yZ-T5nWwMjt$P}!(xg1$X@(N;T;eRFls8fbnLsT1KwxF+h$aO z83vqQjlqC6$N;oYh4M8T6lh?vembtYGf-6y6XuQR4;>~VnG>>C8`X@^zNQ7W>I-vZ zxoD-E=<_CNH164h67+8-KR||i%i89p7>=-|u3ZbP!9xV^d=V0Zd}DExzY>*Ep)=Q6 zH4mMN0NJ#?rJ#s~Zl3vkzOq*~xS$BVC7>v`nVo=PZug5YdzjjU|pskSK= zIaAO;c+&0IFt6NS7^7HP!2wegRWVAOkw}G~(=$2IM72+qW?UED8CJDa#Cnyl@K$T; zxltUTO^~ehXSI3&u&Ai*DRRaDQEqB83sz;rQh1DIe$$8v9<0N(1iO9P+=VPfVvEG} z5Sejcl@=;J{!9=h{|c}-?o&_zWu@uH|MJL_>VA&QxDkK9UZseazV}4p-f#+U>U%=< z5ODQxM?$A<+pM%~fN-J*;|~*=f&~1#qRdskiCfxQ6NQxJ*|_E5v5Nn;$`xuI8r;=# zk}dh$7O=pudP_-AnjEnw!wVvE3A()a{QCWpvXG2R8jettL?r{BK>IE-E3v7bsY3bD zas-U`n!Yx`Io=~b^J-*ZS%1u;lrz;e#A*^HSVy593-00+Bq_GR+W_ZX9IF+24|j~O z+ztirqvziz8V38{v&`nQ#j4eikT>r5>b?-0Zt`#{6o*tLs=?E4gV{Ay(L9RFjBG7g zG|2;&(Mf&?Xs>YHmYd!>9Hma)yR9FL<%9h1jVJA)UD-Fyk89pCQ$w+m{`V85(>XSA zJ<}2jH2}Qg%z6va_|H|*SS;~o%D%>sG7^6^$XO!Z-^m?Nx+*M8>#xIo?tORZG zgoVEI-CilT&3OW21$i<6xz1D^>A~n1%zUjTDi7rv~I6BJOI^z z3%6I^nk;{r?vSK1#rf)G3nrvj6TYfTR-SfI;)S>M1oHlkPc|6nGB*g|?7r4m4wOjU zGY6_mt8yLU{@9~Z7W73V%yV6s-02WL1nx8r4S%cST@bx+vL!4cmVL;mXDOO1I~(?d zg(vhsOt3!05pCf}Q&ey16pUlWw$;vjqZR6=!^NpNEeO=VGxvu&#Mzdp6@uE*ZcnEh zrgIFeT?T7c9budx5lQr_ShwzyD6eFyL_rwIXi0-EMaWkW2K{zz19LD;uGwO3P?E;~ zw-0yR6X#pAO%#vP7iF7jk>mJD?grWW*Wb}2X<-%b_s?>_nQW$Ldy*i6jLCqE7m-~4 z#~CpjC?N}0xSgl0{2NHGJJ@OLRZt5RFZih$1B(+I9+RT@{?W-@Xp-x2RErId;f*2c z8;ze%ZF`tuwqw2C-&@eLpLajZZ~HMy1x8A#0o3xPY{sFF4Z+3RFD=@FqJ>L#=zJM9 z!aG;*W^P@0N7Rm1$mRhkgy>x%v(LzHiqAMKnvCQytv}^2#;9t(QTx2lYMQ?AK}<^4 zUoHJ#QK#vK=WMv5fr%cQg`D~xBkhlFtHJm{XbSMrgYm@ISe#_6PK6>hIi~vFP34jY zK!j0F95kXnNee3;A##U0`3`l7aR8()UCZgzf!>d8qmvFmF#TpO1V=3qv+2unfq;it> z!D%g1Bd0s}=y#fqX}KH)=ZLUgLkmTN2*TS+{MYWP9X3yQo2(==qmzLIexsPT8MN^1 zep99?XI-219r`++YDCYCG^_9hq`^{lz%_+(;zqKdDUG_U&k8;`9!W!-wjXp?Nw6@A zlhf*X6N<>5%4nQ8Zgsk14nhzRqn4GDvBq;b2X6x!f9sir-!+09v6ZsPHPrzo?AZV+ zwDEo%yMo9zhn089H*D~JH3{ut5kNXV+1e0uoPUJ9)jx}Sb6UwP5uD5%7HJx>om>U^ zUov1|y=V5x&70%x7ham<7TdkC#gtr>ol*V2SW1*0M>wjm#Y(fmU$hadBh5Kb{!(FJ z6sKR*tw74g&jLX*A<|c<^Vra!g-DDrUp#I;{VI`*(snc8RamXLEZoJJN1lOCZ_~pt^!Xb4s_K-3j(CB+dE5XwYBlYEHpHyGW=;?0)hNl+$diBa~uYJYEl3 zxC8DDJ;~x~mo7hy;#{^&Y`ziPs)+bfN?ViQDb>928E5bt7M){@F>U4!F>#+odS%j0s($ zY~)f%9+|941+)7niisfi*TWZQwU6}+NK8Yzh%hi4(O$FTiY@r(>mjzoC7ec7ZopA$ zocy{{=CY{Fohbpk$(=x-4zXemZn+fb+O5>uC~rF3TS{G9PzuYl;_>1s18bAveNGD> z=0aT&QUh5c5(k19^70aSxDp2Lz;O(`SmdfRS*P15R?GL2FvQL$>+h7eGWy>>QF`7w zPycl04QQ0higP_99RWkpY!&O3*%fi~>cAh6_`o@<4^5G)l4sFOH;B=G?ER??u-9T_ zJ)wISerQAdsZu`8Qvtu&mYiYZnL5_=K*M4m<{VAFA7@YhDfazSj`I!;n>i#j9mgK_ z=a%zK!3os?-p#bI+jbvbJ5_5-<4xcI251;K!Q7D9(3yl=i+pXmxszJxyrN3=rbhcW?FJAtd6==6aJn57lBcm>K%73;-zm|`rlL0U&fuPi*Sp9 z&Jq{^Fh>e~RmY000r7L7HehAxmV+ zU=THvm)YQ5QT<<_ zkq&^UPhr3zWK{(DUr(e{N=dGM?T4kzf_w&dMx$HOEn+*eTE-5bUiqmg7GhpQKv#=Q zDv+TZ%H?)iXCcyQ*%m(vexlCkrvf4*UoMRGKs&M6P8_(+V(Wetl z0>y_WOGh}#rO%`vd4PoHQHYSdsEFky0(no!h^|~Cp7QG}kshBG+0hxcxcnKj@9uS< zg#||wRh^9G-2dAKW7ppuOb+boszs6K8#A^n`TPs8v(@G+#6sB@@;(#Qu00L`dZ9YnUwz@2+YMF}y zDe@!t#(Q+-_|%KL5!TOx#!wx-ay8rZklq!?4X9jepSam!mI*l$*yqBv`A#qxV`}M^ zQLqCY89kInD^OwfaXHJg=ls%yqzTx_I8;pVX+`DQIVg1+Su?d9G$PqWOGagUHUqML zg#HMc;k04U6ZJd1zhn+;?e7Um3j=Je7XA_{SW1B|TfImI*4;qQj037-{TOSF_z}l{ zX(E@|mbt+Wb!>8yBwh+W(>+`p`D#atn1nO+_3-D*WQa~2%;O5xGc!*?T>wu>MTd$d zoQINLppUy6nBQc}+o6V$bpq9(rECPkh#@$9{q-c+B|n(Uo^;@WY(8$v9RO@n`grdK z!(^xIsN#Tv7blk2yn|WNOVRuG)$wjhPmOR>&f-iIolemED;b?-4>hD_8V>xbPB zshBKQy72Q`3qX;rH_V8w_1IFjup&v0mAVi>HMlz)w_#=>`ouG*-*7A#6NA;yCiaKd zExZ@Y@ODCi-#v_*Bs@;iSlr@Y@Fj3-Jr%&SeB$hTvGX2j%wMRlbY|BdCf_$zjW~f+ z72OyeXt3k89?l!}1N9UoA*eSYpxV=x^R;B9YHw)Fy_n~FIdZ}zn*~MB+HfX2%+(ydAQp1&)|N!F=O%3lk7d$#nBh-!!9tsE*gd|BNe?@K9^=B0Z-jvo{AL-?j`UXVAKbDno8^Pc?VR}szyfJ+;4Wx$S2#EWLV(?Uvj1^`(6y2Gs0y0Q~JfHUNSoroaczO=OTo7h3M}ND_ zEEaMjh*~G2!uk##DKsW?7i`lYCmMjD#Vn>iC@%lX2(224`U{AV_=rQTx&;hGVjHx@ zV06FHcOC-ngxIVFg04k77ff`!{&s<$rFZPgWp!B@QMFSiw${ix`s|~i!(Ho$B$9-z z?bG-k2Yq=sXs0S`MYp!Y=;_l=&*~?B8^D*8bHWe9RT0Fha6_H=hnIqN1Vw2@;hH{`Wu8vejF=~7fH0>YG?KNxA)|hf17QTAfFg84QCtQP;>ZRa+?r#Qh*idHNN&$ zYUDjRZkjOLf~e93NBO1t-h4ftn7<*Y0~(a26&!V&+075TBJQZy#~rCZ;Q>J1TBj}N znIy#Qx>>;I{n;m1OCp~(n=w6%@a`V7J5t>KY&&NwWcEr%q1I3%o2isCaAFIfP^bKq zK*k%%>*ZmssD)aKWLWe6+>R)S+^txfhHG7z-HqpL`as+?d7ve9z?t~eNr48~8N~R5 z=ubH-RKJ828OkzdHQ-JBRe|N3+a_~OG?Qw%J1m5Cj@bMkxTx^SubKrPeDg-#m=SAP z5{F06tM7*ybU$2nlF^aG9dN#1y)CloBWxn9gU^EvCbE<0YWFSWKbF8NKt%^j5WFJ>PVb!xoBb_fbFU|@?Y?-xe6z&lX78}noKQcL_z zCbOZV83$R)zd83t1m!9?_4FpQR5Lnal{xWo$y?kiC=I^#f@p5j;JTi&8SCmCoiCT^ zhjvEiQ-9p!gIL=3abfmC3k3R%@Ib)Ox_WS2f0f1$ zg>$?tss3`-nxmvzvy8nfXWbL=y>-z&28%z00RFvL`QJxo^hYdN<|N4?R@5?^%LDhK zG2wUoDZCuk*y!ogupRn|(J4g<78CSf`T7a(KWA*p9VI0K%jp<1Ke%5nON~Yi_-1IrL-6|__C8#t{tEAXV z_qB4b&xw&c3AKHG;O%7*aJi|dLu{0fJyd*q%>2ciiKkfe(k=;pNa~y1@{v=z$t_zp zJ$4DBDaQk3@U_7xHcnZOd8OB-;C!O}baR`(ag+$u`gc?*sr%HV6!t`yX>K^TbQ6)NJq$2EpSnFG6$)6@Y!)I_#V&7#nV?M}lQu@4gG9D3gCFwo=#+ zOTlluQ98Y)BkdHy^aS-vu^R+YC|>yg#-@91VP!XOY_Om$fB|q`Wgc za?1TzmXv^!BG4$&JQ^~BcX8(v%UBPAm|LcN?et6qxhEDi0%Dh?+Td6-+sc16;tl)% z=q|&C&MI^wCd+Y03hGf`lZIe9*>`C zKZTiju}*u5-In8_maRScC}s}q8`}s+kqM=N^1nIIA!k8*h=o`=D&Qdb1z?Hc^yF9P zK!z)hVdP-c&wK*E*FtFW7n{d%NO6bH7eF4RtNkuXBW9&7tInQN#AZx$tbme=89NWA zA2;ta5ikdNa3|QHgNLsKI3c9e1S(>eWN<$t`-GcQx0l6i=2Z8W3UDW9_bQ@)TUS|@ z^>L(wnlgo31>+O_X-u;b{;ZqKxkm!%~cD-%}5nhcKz=E1J8T1(7Vc*(V zIN%obu3n;6544;w(y1qXeLvExtHbg7!=-5G^&@o01B8_XLm%VHWSh=t#R2rlb)p!i z*;0C9G_xsZG-!gt#mpKgZzJZJZqs+>sX!X~C#jxG))~X(`(;EPY6rI9>vRDBmm-FV z$5LtJ$x0Ad-9}3Xh0M|+#m`f2BKC##*e?w8E2VKdTF-TOjE z1Td5CTMV(OGT>5zUPQVr+#4GAqOob$8Fl2)yH<%-Qf00@HC^-T#7uhrpQzr9% z*dty6F~rZSH07pN99J63^RAdjmij@{!L?-5kCYABdE8nWj$6*-yvG~-$bamw$lEAA{=DUeX#;w0%PrTsY@N_;_Q9#; zcjC;ffeD9-dU|2;zof<>&iW5nj8F!3bx%;xp}q23p1#}2c&AzQgssI?4Nrd~Se_cC zYM)sCY*N(lfhM-rQWR#0u_0<=nPA&btVh;QjJ6WJ7z5)wNPDOi97Yu0 zI=;9ZgCXwD6>{U=fsuS*)%Dd1UhW=~`@KlmRYMe=0002yL7s+Wlw|Pl00B?sKhL1N z!f|y4`-K3rtZB_$W`rXqAWhdckXD5fkQGWAg~pmS;p#-|LRq`MPV2ReSU6zOmi`2Q z=*Hw*>)P>DfE#L(AEMD;~-A_UIJ? zBWWBI)J>xlCziL@e$g>?JhlRn)@ObhMw1Tm6B*oij-Bz`4!&Hc;nJmdq;3Mc;fE!1u8hW%zfItvq4oN?2S4MIt$>yGmA^FeW)+$VI zT?%&*O!<|o>TzJ2rW@Em;@33{??4J0Vs3qKr)x)yJ-qcVeeGC+zxMA*>$2> zKxPIu#rZu+suEHc;gX`wBltQE!O`391ZYEgRz8U}WFt4_3MVL1@NvyXJo$5s!mFJW zH2n)gS-Sq>9>G=geomrkIe2lV8)^=Nm}x!S`A?Jwu?y!TEUUfyzn6f}`9t8k9XQGc z!R1Kk&F+1-C&2=(Gr*m#8#T>4)-w=ExEQr&_rKJ9EB%sqX(9hfG10OxhOh7i86o{b z!#AC{lM?-UTux?{5;JPhws;<`%UN0awt(%HMdL*?z)jYqLzGE>bKrPHe_2U@wVStP zMh*O;WsbN&pMEv+^-yem6+#t|n9@W#QdMO%CUYs78gSAkk4Ml#XglNHw0`r9X)mp1 zZ;jL9DFBo%8hXJkbz+p*lbi!KfiMT*7^}Qd*hW^nJ!%BF21=rj8%L=aGgy(ECK)L} zWlbWFBuP0Ic17!M(jq?G(sq$1$>5?NpyEM2FDnyJSkh|25<9P-!Veg;Z~$CU5e6bc z;e@(?tqCIzd&bjVIgdZJl1=%do$-X;ezPg_+ycj==yyz_#hB?IIl+i(X|fq_iRUjX z#|E_y3GRD~UGK4VvIQzvlxqnyiX^rl-*^o`%RQ+XlAZc_KT2Oq^)~=OND9rhK7Ki5 zW)r~ZbQ^!)FY&E{umifn6zy%kvE5gR{dqA3y*#)*Ca#%d!x9*)I9dn+9Wo-Sq4P+| zP|WLysiTa|(JiIGg)fu+Nj0?gQhVMwx>9P60%XS!pApaT*O(7;`2FpqT~Np$D~R@J z6lvbTc)lWFv48s!F-8?oKL(vYb7OW!elV*KY};i;^lrP$&nK+XQYsJ>>7=Wjv!qN& zb4AUVwnfn>j`?zA>A@uA$Ci5fRBx0XBfH=i4u4h?DGmrh<9(n5h3e+vD<26o=>Uh% zNhwfPRIukT&EUV4AJZ7Bg654$Suf|BBn3-U&AOI7Mrm*R$PyNZS<6OFF&51@7i7B( z>>j1kQ|PlP1>R@bvZYno3PMeB#x2lNPru$_V)MQE0-gP$nBO!J{L9VCLu(%7Mc4FEcX#~87XAa^gAI1yclC2P6H4n|)r?QZ9e zzTD#zi3-^0VecpN^$x_2nq@MQYFa5t-zrr|8wwE{Y`;dN`+&zue}lO>zb&?9iFGBn z27r}x0H^y}eJf3x{_}2C)T6uYw*lez_0=W{a6TlQVC~8xie5hW?LsGNLY`nQpcQ5g zAH1324_N*@xj9%!@NC-s!0lfdr#;ONmrnvnpg21_+J&~W*u+) zwf=Zrb*RiP$W%=f+`-mMmMZK`6CAeAh%Fig?cR?893Z=zzZ8=Q_cp^MgZr`_OgagVG3kDnrCTTVKY0sGxw#_n%A7jTVjbPDKr~}W|7vjo(0p5 zM1;bxBP}YtSWlBdx8pM>oqt6N=?DgaZNs<2w0#&BgN8oAV z3$zc;rnqzAk#GS3R?%mx!z-dz+;+EKcy9amP7ij}1b5N#+ke2>Zs|y$Ow2$XQgQR& zECuLY<={#r0(r{;PTw~85@h$3eH9>qD?(&kF^yI@WH@?TOxozt*qVB9_)FkZO&zfa z?|~H%w*SxMK|HGkwBGd0DgtL5VOg%`_;GY3oYNN76_>kt3K&Z|*1qE=L1`u(K*+^U zLd-{mjlNPbCUOl)H3I$f<`8#pzk9VSb>AviBQ-rA8)G{urp`H!nIvKs=#97g-gex@ zJ;eoXOpQySoF8CW2OOx$qC#em|8ofeZ?9_aY$-ymptYGwV=p!OeNs15>(pf^W`* zZ#0G+y041|q_wNi&^5mIrnUV7<>RP0*ev>uP+SKl9QXJpQ#OzEc+)Vb9`ndQ{zUJT zq=BOKN|#2YC)&i1)al{qo@g~DK6*7`wL!|r2FEAYSYu-G5^rY+KkjImU73Gu2eivB_5l!IA4tk;nFt z_eyRZ>cT46zL&CCK-n2|KX!RTSbovhOs~rsde>sWt1j_ zJY_iYis*obT%)(H&H*;~OvBDv!MznuENImDE$&pE19K?Rwyk43*|F_p$F{j++qP}n zwr$(CZQH&%_0GFh_ZO_LUR7N^#vJn-66+&5{sI#)d-tJepu9`8Cp1DeiihN?F^p!A z-@Go5Zhq#quP!(4>dE6n#kase9T_VY)6Y@eJcoR>7+*`NHJiuwwlS#Y8z#s9Wq6eF z?DbMWs?}mIp6l;5t6g^dHGm#K5E9dDwiF`t=)Cz+HC-73)*~S$VHgXq zkKL$fCx$>pvb0eG7rnk+oK2+3&q89f`<*S8s13fzJClIfO@{(zZNGNw1WSD!k@G!G z2*8+_#x3Mn7}C13X>J==TU{*)#;9;o-V;*NtV60({d7%Z>si_~RZ1(8l;WUNV=px0 z0h*NX3!d>!P|a(I>d{x4_Jt}mF8LUm57G70BC>|^{97Y0AT3xgqI+r|Tb-9jI>4Yn zG-K5m`76+`?h*=S+{~>}^C=R{_|zIT2a-Lg`gkU=8lmteW>Z~_8%dJ9@R`D^+J+Nu zQ1N{oZ1l5SPOArU0j3_Mk2XT4U5==YPu_Nj0 z(m&}nx(@aOa<)W_#((wsbPqt=|Fg@eFgZz<;098{2zmY%YGx>au9eKUPEWxEV1UGo zoKYfA`$9`*0dONsp(!!-tQ8q#9l|NZ7u`MQ?#`r(>9UENt|;`X(w%x09PupU+^Z9j z?Y6MQ0~}mjMc!7gyLh1)&1Li9&IcgbKZ-6GmD+sBt+WR4UBK61Qs~kU6~6(16U;%Z z;9wxiVO$%0@uy1B=f^!Yb2AQf-@+7ib`rj|KDf6JK5-@lCcRj#FCdKVSM5aeXOI7i zTq({U0H65%3vz^^68ab z;J{?%qi>fhqEj#mObGz&B$og+$KnO{k_gH5WgIDmztM>Q=&!T?FGha>N@vYxvH0Bs z6ZgBv_{2awW;@)uT;s2d!X_~PROG7&(}&z+%HT~j^Tqi^w)i`=rj+bHHZm_xXWnwU z96+9VqKc0ATJ#E9C7{?d2!jSae-97@%)a=Kzyqx~kvge;hn|Ud%=psh-qnEnfDmU* zrtE{jv8qRf9V!`C>WUf=?5@cjhkj(1 z+QEi9NBkdn7KdJ2xJ2~sFq_ss;+D}IsbG{SSNtfBgdQFzE=ipX3wsXWD2Zoe4P0BU z4-3xt!uYkKH_PdOV;W*hCUIlqJy5*=_9|Y5kEj4bTwKOC-Ix(Zb%3e~<*7!{{YsaL ztiSQf$$iIp0nR(%y*(XIN{sBmUjYGP^*pe{2CgH01&C*j1x_{}tK2uTQqpkyoG%di zi(K1hGU-<-B@}3=`)>pIFqvd}9HRtbo#A#NgQv8bGJHPAu4kWCTXUHz21~CaYRj9b ziX@ry2oH>`dq`E6E6MncQ=^^nE#ju)nrBu#G`Q6CH9^!}twLjF73%gx^LOWeFFs+E zlL1r6h3Bg`s{KG>0^8ShiH9Js(%heh;~(1C0eA<;ADj^w!zbK9u}(P4J`?-~Y2wKh zj+S5eq%60akwS;=VWNaJzQ?UgKZdkQ`qbsv$gsci3XPh3Gr?L*cG3{y0X&~*VhRp< z&A1J+u1=D-NBm$w)m#WT=5t4eAF`?fsp|^zA4#Gsyptfe>eszB0x@;o$hrLD=sq}f zg0Ka%>Y5Do?d?ZV{3*6#6q=87%`i{s+%?1-4yS}xMi|sVAGoSoPUu+-z$FoMB|VG~ z9t14P3-lmvR|YT?R74Wc#SQes7DY7SV4&ZyAiGT`bJ_Zy_xRgARr(yI*`C!J?7?pS zZG#h=e{8zapmdMT)U}l_;BA@!@{F8pt+sU`SuMeDmAFHQtM8UIRX#+c=>*&yLxfb} zQ=r-kOOW~5`FY>_T8ySdh?oQO)2k9yw>5Ek{<2-Jfh^&*+%8Bb!Es5Dlu70M7>jK4 zR`5v)kR%?Y0R-3SRjWs*F^_jkoH$j(#C_#jmz`FxY@1`Dl64Cf_3&kv-)>9WHC_F0 zbdBceO9AacS+De>NXLemu&D5&ckVn@InX(P1wSLmDNrz}IpN8VDE%VrUQ(b#=+lq~ z0bNu-!#Os~moXXh3Ep4W2PMIGT+&?mp4jWW*R{|dO}Od8xH<6QR%c^n8Xl6L&GgT% z>G!3E?OTASjD+y`(x0D;!_kmWz^oqtJ0ho_pec*EW5FI>l6A#-ZqEM#ZY}0M>wj(o z5uQa9HhlW7A{A=3Rso7@tJy|>U0`uc50LJcc#+n*ZS#N!iy$%*QO58;`Mu#ezcQPM zg-o0bNZ9s&a?0HOeL;SpQI8B`M&0E521c@Q=j?9%HGT9Wwk*A>p9fJHusVfW*E zq1j5SBoJ|E2K7}Qnd^HKK4lJf3Npxq=RiJ5+o9Tj#@3 zi6oJ&KiFRXlwRP@A&R=cgzc8?o(YczztXPat5=K2&*bOkqEGNfq4Q-OC&W6g^O~n> zVkhZ1)9Tf9e^m~gL?b-c*}*GHS;?T-n4c@5{9ye&Ww=Am--c6XH}*& zWrtxj=MbNi(|L5e9$?1y_DbkoZGF5^B1!pI@(->wEPsG(2c~ zMv~1zn~v=u7J}ZiDuO&9s8X!+Q)@Xu~i?+`5%ge-}PzG#^mRTMRhamuaDhBWhMdOX1B#+B1 zO#&=Kc(clndrA9ujkH=MFHp4&OfLile6cDF1a$~mT4 z6I#M}gw6X9u{-JholrYs3;k$#{e&XFtdMq|Y|t=?0dTT7C`s@SwBQF+Y|JrHAP z4w%}GceV*KbA!RfZi+GPg^-zLFx@4g?bgsf8S*H(76PLwtx~$&lWB*}v4)rZK6Kp* zmpWsJw@c^4XWqf#C9f%=0zJN0Y3m4iEPuC@+Cw?lx2|T|`*&}jO8GuPM{RuEZp=1h zG%(ptinD^eAAsaG?+GmE` zMz}0u_bUT;Sv!$47(7OiJ6wfX_@5YOM#mhzA41F@eU$SBRQ)hq)_vrPz zy<&RG!P^+$kBj%PsMpGLy)rH`G4TF)m%48awP)?ta6N4ita=tYHe4pJ_7FpI%oIIu z^7p2)ckh?%YzD>4O+*Y75%AFjJjsX4r{OyeOr59o&n`WOV$MJ-ZdNrkfdb<#gmt_= zY5&>}#f`i|(iT;{WF$Iir-z4#fPDxeQp&i%ByOtF4 z{ah5fVppL;^9zP{X7`91r`m1v;2D2Fe3Z0i&X?e;o4L+7zIZ$4SvL6H`kbN6q+-bxjthDxk@l#RPhR`HK)O*HV)ih2(2_`$W z^C^lBriEuKwKp-ZnNbH7eu|513=WUO42b8t70PxE1_`k?Af=R-B&GhgtlHxXMMcX) z*E~2Q59X``>mR&rE@|pIn+-T7TQ}$sFxvcF`Sd*on*Dz8z|xVnkW{WVzK`g^Bqfi{ zYcbpZg0%3Uw+YTybSMVv*6E7z1dq#e-g&!PvS+nirHDI)kT{2AGcw_9rKlk4F-r|9 z1?74WY~)GAmw7_IQly6mgrt=DkMv5_ODEGU7goG0$TrHsS*kpP}O zx%6&C+->tvUTbh!thm(5n3arFp&!u({#r>I zKO_%LCqH^EW`q-%P*+HD*|Iu*tI(CEyMTJ@XFhNa<;CQ0+XM%J-Ht^|pZ75_@g_0#HfyAD9q#o%KS2!iKGD zd**us!Bs_z%g}*|kyH~qRvdazV?46YGh`vKQ0_*}sGnm2Z1Uo%RY31REzx0ei`l2X zR63r?r0P~*3uI4xYWpb^PCpFoon!UN6SVQq4ZH}AAUS{3Ojrf9KWR6bI>fD>NrlB< z9GaQ+kK=PJwlp?4`5z~qh)< zmJ{MhVg}LzKV4xe4lL$dg0MQpbjwltmHH}qcTywa2Y@inNZ2-l?6X-p_1bw!SaxEE zW>xJjXz|1rCeR#d;sC6KeHH(HGn^}ey{Xn4y|N;}Fc@%6lE_qM^=u_t8VbqzaFCt~ zzA6XsYgtR(%uqrA+(5a-*c@P##i|kH%gT;Qs%&&yyKlg}xgnncN%y^s$dPogEaB-j zLp2{M^jMjWIWzvPa*Q)RMCl>LD5g~DfMPOR_Dhj?xYI{G+c4S>zZ}J2q0l=?^usMj zC*I8*r#iT5;>wqPP|KG@h^uod4u=urtO<+Loj%p(5XH)XUr7Ukj{aKo30UKkv9Zv(V3CGgnI83L z+cmXScaOTmT54379B4z*?XI%JTItyEC`ZQKZFr$3a>BaZx3*XDOARf^Ih2 z`EZP=G$wCz3S~W^R`3R2qJ8#BTVDCLWs3UxY4#G^ajp5R4P3KVX}hSOFYwp{I9|IS z5jDqw>Eo(u+xwz44W5U6efC7m8P{YSElpV(!B?JMpVCNpQ%$aJVZEW5ri~}_R5;6| z%D&d2;k^Hr*U`&s(_%K}ySE1!mMYj6@RB{!M)>plyugE6PL7o`M}AXg7bk|OKV$%z zId}=#0-Eu(#=4%ncaBh+2x+-UgL+iH4GmI~wET;MB(UEAFQY+CQcY{(x=h43O&gl_ zcAFtDj0kq>-v(^ds0i92@Hotp52NjqYYW?k*o8Fz5E?!v7o>?27Ga2LF)E1&%EZS~ z0zrOt5V7vY_&fZ?FcgLH-X<}Gzr(EbNmx}H(Vt)$Cm#9SIqI=Qm(HZmV88sPsX_r! zfxqpRb4A1dtWIXlQr*o-@SAhRWI!1W9$LACCdDzaD)_(tVB(5C2LD}!H|{viVm8rS zqhv~+1l{KU-lVSYer7{?wS|9I73v?npeIZQ_m3ZB(=MLzFDnA;dm&aQLtdL9xS7V2 zmnvxu$!E2BiZ2ca_t!~wi-j?;1DLe{TB8*8LLZKo!_fXl&+&*MZS;Kc zZ1bTgnuw{JO0c04Dgli&SqV~T7L$pmbX7>YkeF$<$GZduo3{YAZ^qU(90W~eJ^-kdU2_8o+-yT3Zb zZ|R|+1nZ8QZJD_FyiM32frI=b6QxdrKtcYqbBFWCu6j~4Jk~oFh0E7c3F=FE_Ne4h zvYASTLx{1yrRo#NoEtI&)XT*kOiQx<($EBmvaU-0GXBo%Ug-0y~ z${gHUL?Ou#80JP5_j1jOoc@u!y3iI*ybl$FUe-Yv!D{^ByzYSUHba~|_nG&$Dzu}T zEd6nnJYUErIaqCWbm6E+X}k+2VRRAxdJx(2M$5gD7Ir&3n(2?e!L066(AI$bSp0Pk z+DwI|mJPo;WkQy@YWB|=BQ31NU^CHR?e1y>q0nGoC-yf|nau3@6?{-6NiRE!4HeBY0VvX~N0Y$kx|p99oXxW*L#>TSBpJotO7u)e(qSvm zkM++kA@jd8go&myqYXrd5z<_~kr@|yPNZ8gQQhycs0d z*19C;-C{I(+9KJfD}g!tU``7%KIF5ttIbYx&sX)u=%~o6w;AECQcZTaL4!zL0}ktZ zihcK}mF!2s=0*c<)3U*1Bzp*1X1uZv;8Pu>4|RPqfhNvk%@OcI2fIJ>*;t!XvLU`5 z8`mG9O0V(IDcqev11+9J?@hx2QD+O*W-+*)5!!nw`cbp{!IyXv_9nZE`Y-66mL54$ zqHe;#Vm489Q3QmMrIGrwOk-8}FVw|l|B7e=C07xfbP8#+CP1@MXXXa@0{`?Zp-;s; zXwq4`dJlJKj_V^kCraA(@pfr-+Aq_N{T5Z6JpEO$I(i9&jhpO1f33O{Cwt_b{cb2_r{Uxt!v-d|CQC| z;8oY=^-@43>vAJiScFyvR`I__S(njmR5^~RieIgs`e)dgdnV>Am%;nHO1fZW;k%FQ zItlqtx}B3W*lY`o$i;go_=eXHO%Gn0{wk`XDO$*-s@eV2A#9cdSRPfdKfYlydva3iCQGB;iefat+ zf1IG1m5xoO^yX5h@cKK%8>gJ9&X+KMAJtVL)mUymq#}rJ%-bQcWs2x7(h{42=?)vS zLnQDvkJI2Q&sj7_YZ@mTZ@Pe!11ZS5q*f2$E!aJ2-y#Ve5hD2YV|ygqm}tkIy6?M> zVvhwa8vUSGSf``xZNawbb_DB8AJx$TH7IgNTv57A@yOqNP?~&kAVMe? z!9u|ys_{CR!#Y%Cv#>%gGju5?lbzx44$5;1KX{KG`gaV?#{kjDW6V2vna<}XX)S)L zLF4@L2AYM5M-?WS&%>%mypfQL8`YL})dB0Za@oVuW4KYrt!3_$8TqZZ3{8;H^8zDy z(it`jqkkb+5*fPaH9Zs&>A%$1zb9qe|8RC4STNwJk`$+vht+q9Tvv&YG@YNLqDkf4>?Wq{KNgyc{{<5i}O2YN7BuDdMdG|*+HJl$tjXI9? zfs#B?;UJ^cwJsln8z8c2ji0_aPAxK6=OH(iTp;#)8GGH(lEc>?b8Ynvq(Jg*P?318 z2ztPZCE*KzvOdM*NDX>Rqt(wjCaN3f{XSB@j#;yjGgH99RS;^Yv>K4_CVSU@b~bfL z$1_(J`;pSL6%HGMfI8rAZ0!Xe0hin)_{9D3@ue2S>oPV$Xjasv_wJfyHy98AmJwa< z)`uYjfGtn|ZpWjJsc7~sY_U>kby=ESh~U}7)*D)9r-=lUpUzZM%|N24K~x6b`{wib z78-sg!c{@pB*myPVbw!Fs*u^`u=@l9WH*{RkrF!(Oc>VNBrZYaewXN8vAY2{oJX?8 z)-nDsA5OSEw`n*LW(a_o{xj@n(#tcUi|;fUJqbCfn_ zJ5ZcMOOX|bb3nA{OQ^x2>p0y)Ay7&tiz6=H*~~9e7q#PHGWN04qGJoFaL?%8gdNeJ zeim~1*D2+j?1}cgLo_8hR^2M1CU62abLZb%Atz^T{VWuQntIm_Yy#}k70FRyPZox4 znMDJjQOU6}{YaG0N3I*d>J}d`AaP5{sZKh;eB_U0oVgK=BB@Tgqbk%HcZL-PK$F3l zXAG5h(A7==M9@$&UKE&|cHG{@Zz1Lu%8j&T(>t6%m5 z{4W!D4lIWTBsl7>zz1C|%?57|?#)fDt~jh14O)<5u^PICB;?^e)`_xvB(ZXb@TT18 zhuo`TgKuBo$9)obXkU^hmFMTAHdo8IO|wnT^ypFn>JtcXxRZ`QQ+UT0(D&!cCUf3~r2#p|>202Q} zH%3FdL;=#gjS+ch`KS)TH;Z>UyhjvcIWmuZL&sX?$`Cu)={|VhVj2HwFqX<~3!PdUyVn&s%>!__8N!q+&;l7m@;V27L3!=m&Bx4OzL+ttxq6 zw`=okZWcX@h)$>d#e(ncwbl5s<(tNSeFnhMV3`5s`dHjECn)gD*a*mhv{EE$tJBTW z^ws>gg#{Qv5)4g-(f52AZZtnnk`Wp)g-vVv37Z2ved)sQ-jy_3M~pQYtK55}8w)$& z$q(~mp*zKsO3DdXt&g>G>~ z*sX$QEE3f_#7}HdH7cR)z_Wjg36If!CP+O&cxlR-*P7|#P){-U;pzHKE+;=Nt<%9} zfhi52z{O$!mv0_LXer+x{PtkW zey9uGrdnPk$ic{k6C^sn#Q!Mh7v1>-j6#7Mt|v8F#N+i&p6JXY z|FobCDQG(S4T-SYYHEnPqFN!cnn`QR@a^PywQaik)H=5WY%Pu>ATb{M>N4j=EU~g` zHLEa(x($Jd^gNC}{{yy8Qk%g8JS}RP6UCd*6cN|y9%+>ZNzyc4sb2CMdX2(@3Ni6eTV=tFdSLy4>MRO6zCns1P|#@&S(XlR*~P z>%_h(=R7m1PuhXmgQdIas+m8@e}XO<;dk(Di=PBXy{m74KhAp(mmo7L*DnP9xR6H3 z9BfNO&I(HDB~`4{Xd6D&HL7ShWS3cYywA)gB?po8*@n;83e<3=pn^5n^{N`EVvn)> zy*v>z(x~VN2-#+lhF=lR4F;LCzh)SM%((bi5D9TnVCKeCo4o``+0KF(bD!Z!J>=hr zl&V-DSkhKAwig^d7yy zT$>BWF%*SK_Dt;mQ&nf2BX`M(t0%gQW61MDjP8Q2%_16%q0y*~#&)%|amjzzFG>>J z`KYGwsvh#MhW+qXH#?t_liFge)}>$GY?IR+)dNIgn###OnhHY%Zc3)$Ve{0fVt(nB zesxcozx5VJz{>B<0pm+;8^-YN#l13El*BCjV%S2S!!g*prkc;5Ia(3@J=I}O#)k|) zN(K2&Nsw{-B$PAj-P6ObOw>yE8_u~i$Y{H%D)} zuT#rGbLDYT7oMcQtx;LfOSYKq86-xP7N?DoH|2;BDn>${Qs*~)F3Fz*_unEgAWH56 zsSPTtf2!av9os?rjo#g51!nu2!rGK@<;x^%6^bfZv^$FISZMHQ++}Ad^O0u3i_uFz zL|5xOI)GGU32k4!s#>q^J0!iZ9+mVjP3}`lG*-F zzoGn#uDV75{5I*}N(%KWY+%P@PgE?XFn^}2ZZ;6?M?~D@hCsjpAfvUh6~*{5I4^a- zB>L*?Ojohw5dy>2>Ju+riq-Vh$2b`#KLtQ;6# z!8jt?z2DcF4wysppZo-9O+zm@mhZhHj?ld3U(Yp8#X6f^*3c5&Q#_+XBWP~JLmdxb zY`*h3x?&nL^edYJ3C3(EZmOuHX{>9Z`pfE460=3IygOJn83%R7$t!E&}Her^^?A6j*m6Y_Pu>>k3y^z+SjBvN{ChSm8*G9BWfgL3v` zy^Jgox8i8tHbM@xXI_lGr!e*yp1fStK8}cH%~R3%Ik~D`=+~R4??i{b>g%C!tz0%` zoat&S>oC(eJzT`fOz`@J_fFbSG7`o;N7LzJrreZDsG&eeOmbZ;i$y=rd?2{3JGXkY z>m=Wg*1Es|&oAT9tsO5!Y@)O@wr9gHR^QCG5#z)Za70$tnM#kpNY&sg!fzsQ$hu`} zPr5;*A1}pA9~rPF8SVoDqf&=R;m4&MG)UZ=g!*9L-*!1zSHiJJ&5oiJJh;#~fb5TQ z+AY7~6GOlpy8qoSIBx+g5_frffmV*@+bPpc1qJHXbjGO;k|PmnPul&W^gn54&I{la z7}#=|48S2e{)E8G)IF8frc}m+6?;~56SzX1*}8tv={}YzUwj8e`b_6#HF~v30sugw zXpOk3Fh-`My$ZjCi zy^qQD$aMc;2FHU5LPJ1?HI40eVfD+LLhfb*HmhOH^QMLi60l=YE3v=`EY>cemuE=+ zeIy?Urt7mVh^!||OD#w&Q?5jZbBM@4(wI8VEOkiV0&nB<6Xihecr=`wr$&nV^cSN; zoV5nbJ!w}>1)Wc2FwUdH=DFhxf|=r1p{0n(&iLm_Z_9akDw^qdc<2$MJ~Y=-?y#e{ zRMlJJPpCeF)9;;6WY1T{SbyX|BgBfU@GJd+lGXFWD#-TreNkdRr0Nf533ndO!Bd6^ z^2xv|KR!j*;Qa~DA!tgzYaNXhRAJnVZEB}>ep@(1Zm|CxDBSpDhYb@wmw(d(vDpy=JxcZa+IN<-*QfPi$=>bdQaUa;h>>kp2h7hj* z1#m-eD(UGGvKD-pCV#vbh6ZE_O3+v2y;Ho`BM?3tMY)Q{)h~M(`?|H2q2G z-wmP13o8Mw!wEYYIHNoTF-~LA1NWHXn)u_yA57}xF#&7Aytln*s42&K8-& z_x?*3n<_+-@TnHvnYTd9V>k4LQrmM^K!y?Y6tjt*%@v-~!0v_(zCpLB>%3fkq%tY{ zU7+NNhdPlpdF!(_B84r%dCs>2{818}5H9s9P!QGHr1Pz~kVOH4Plzz(4?wf3ZWr4F z?-;^RdK(&g5EGUh+pC!Zp^QGUDl$1u$8nTyY=Is*fe6Wx`4wDPF#L{kLn_e*S83<2hDu=89i9~>ifT7tl@c-2oM&~uIYFmU-W33=zE2R zVz|?vvQViMj#OKcKAp-=1^tx;7!M|1v3VPNPy&a@Qg1tp#6hb)Ae^nMDc>ZJ#A)32 z$#%_ajvfK4gV)w2=PskWy<9OGfk4{2t4`2uV-%SB=Ua7l7=n)9IZtlhuT1wgpOt~w z4P@xcM@a&6k3dGSi+OU#v;Z@Lb6;(TY+BKWeM<4{8IWl-yWamc5$>(>@(O}=9a{vn zyYWK{E7G6@cM3zUBewX{ymg8|9DvLbto3HLT3?=JT-jO0nSVD3qQ&XpH0d2t=wtK< z@YlV}uV*Xw!w|L$B!gy7j`fqlwFl~9%bWE@q>9)w&~vqKI55TJAFgyWaI&zRR6w_Q zyZhqyY4@jofe#YMDjvleC9Dl(i39|2s+2|iGionUIvX`}J2E+PY3&#{bjW0^4~H7u ze6YZB>CQnwYZr|zvrJy+M)FVBDc7(kf=~WKG(fg23|hx%(6^C}f242#sZXYy{Fi)F zD0E=rHP$G2O93Aw<*I;TZ6PzI+nZ?3#+4~aMx2yAgo%VwTnu~9 zpckNm&ZkpU4AZG`u)vIVMKN`yq;`@T%+~>ia1WIfY8Afe1l8o#Hkwq6AW?I3Ih8b! zQilyr_YJ%X5j?hV+)!GGD6;+0iMCuMgBL7>W0${HV4r!32dQ9!=g?45)NMQ9xk%Ur zHz=R`wG&|cy*L!k%b57;^pPNm@#QW?&TAV|oOwkm#$JI|A92x|%eGm?+AT?NsrPog z#7$bcs5kfDqa*QB;8skDL{BG{<_7bUFM4@UsMu};nIAPi7OG6Ywq4}VH&$+ksd1g5 zA75*;4BF&dz#Riw@Y^ay8^NtWzO1Y2#v$>`Yh}7I^3u6#`q?zM!y35f=?5WFc0HDM zPUbkDTD*kamP|@;*%(tNU-+gWBwqt(E?RP8nW+zW2s*cG27JBLwcmn{TVtkZjryEQ z6tyvvWX5|@c;8$P7`#LD{RZUY?>_m3B=Rt=f^^eAt$sZ_MhLvgEP9xR7L^Ev%8x0^ zxTJ=`Bc~2V0e*yU}IrPO03OQ@hbIRx6kWBWIcp8{j7ylnHzV@`S@`e*4np zpBjB)RFForoA(jWIEVNuHLo3(jC@<5M+3Q)QgDvnO>3WaCc;G?-8sRpX+t0c6*Swc5=40~YY4PW8BS9~NLXUp1~PU7K31av zFqit#;{x<*=|O+4B8x;W9QR)p-`Zf=#+9%Zj&0^4JKW?X%TSv_YAcKF~4b2hC{d7CB1ZZU6<&X zqf7!f;|9$c6QfDk<^RNCooXiCYSl|MLy~in>Shjng}$>vwuMjF{b~-lrZB9-MWBcu zx5P(K^mIkPvu(KwHbUd{X;KU%pIXPK3|5Iv6}`G~5DCVAdo5cEvS&J_Xb@)n;e(x( zD-u)6329Vk`E8n%@%%t3<7rZ#>oQ@p!ZmG_t)7Jmece`^n_V8>cz!B-3%_jMJ3*K& z4y5*b5A8#3J9pVLqy;(ez()XQyA&URfeSM%Brj*Z!MB2%tB7Vl>5OQn->h4*vefVo z0E(=5m`_p#a2bKd_UPih`jD20$xXPL=>*b;H~%xUKZ2)erm`sFr}2T+A?Y2zuJQ&a zq-!ergCbectbr?!7c3;&vT?L(LD>#|OQ9f6(`#wE6z)I`I14E}!6Yq?H~XFUj!0Q5 zsr45VRZ7Yng*#ZDi^z0jtj*O9_!;PD&W-J2CEqc7%h+!bSdNM}wATu52NzrBmwZ)e4m_ahSf`5TJYrzD5ncA+-Qal_?g4D*?09-T1UWm0~yT3 zlP5+V;7RQxh*2pYu`8oZS$)au?v?e(1ibabwS^XfZ}=FG{zNdpgZiJ(=M{4~i_ac0Dw--Me`o7X4 zP7eEZyIM5PjE2+7Ak&`X@$Sqfiaku9B=J0U)5*b_+rCnj1wx}&fhqRUDf_-d_&CS zLje+g4R0!iNCMe@!au6}Lf*XiY4#W6H3WT6e}mY=_KX{Qh8_oCv7o^w5M|yLZA7L< zAU~p;AAM9+3hj@sv=W&86D>z%US@ptXza0rA=C{T`z|MY=Ll>s54*B?zDDzvkGJ(2 zjSR@8H?dnq#T9P&fn=y=2e=Z22Nd0PR1Wy`4*VCYXGNBO z8uBZ)q;tU%<3JJ<*aD1Le1CxRAiUy2qdB{`qF!e__J-Dc8NF+BP66v|$@HYcx%|@Q zMT4~#AYR8;``86xd|ZdP8*J-)ps>v+EBlQJF z6Z=tFG)b=oH}`6?LU@O^1!@Hs&{~ofc^lC5afPG319By@<1&_-dQl&RmULZ|zPclm zs?X1qU9>cwT69Ha63b-0t%D#IK|z9&Ne2(!OH7Lqi}?&W@S`7=MfliTd-~Da>}z)C z7hsv82;pO~nRe#tnSCdc!}bKLA{G|ZWGVe?EqfpeKiwZBhI#Ge$TnCU3A2uHfYBla zxv|+Uia#^G#8o;;Qw3G-+N;f_&eKk}D(x;`jZEB8v4t|uixy4zcgE#mWoH`YYvbR5 zqrB%E4d_V7WDlC#JNmFoiic-sP%`rO~zlV4V#tEP))fN@2px0o94iFgcth=)s zEre0Hi>Tdh*RrzvR{)?&!;2)xA$6y3Mk-ce%n|Y^Agm?jP#D_`@t}>uUsFh7Kp*bx z)7OnS+`1WXd%L<(00sw&iGS`?2~Jddwtza}KOHxvCB8G3z#fPqTp_jFL9G2|tLJh3 z`#Q>NHoULNu5D>1^qs}Wn#YIz4vmE>mm5k_0FvwGGS&>TWP?8t?I3k_MWcns738>% zdIFC|UV;sft#2}?Dj zN-~d0HWrz3L&hqG1vf=4Y1F>as!57L;l9u-1PYt44#d-Hphff}96XjIr@WA65o07DptMWPBqjXEV(fPvX%68 zVroW2ovZi~l*9Z4(+j7gTzLs{h?)BGtz@Q!toxO zrZ~oEgCV|BNOd#W;dA3T%azX#z_q8W&fa)C}fv<-4z(l1CTBfU{M$$6%lUPAKgVQke# zdm(#y3YN{$xtz<>6pkZGGwsOh*3&xD0o!S5@RG+DX+2LBkbDFKaMAF1^gAdp9;X$vUCLqjM0*?hH}TCebcj+fG4 z_08s1cMzXizOKgNqD;os!m6EYz(@Pr_{F1OHj8Xu#alIq<%)iP`YE>6@uGTa-J%3> z^Z`-N^TY@KUBZT0c+*tF<4+_Y5+fJOcg~i8vc^*j6@) z8|(#}-XwT#9C3|Ifg!)ruPbH8pCkWY3l_XDct=S2Fb5dNxxwQ$4IpP#Z7vyD$hr4! z12Cf>;&xOP53dh@ky`vC0qNec_}T>U$O-aj(6OtdFhMz$Gr?A92J>_f^Az#t4=iSC zx=RdWaG$2Lv+H)+g5bh7Wa)O?WQLqy!tbF)fH`*mF)HB}&GH2#zxB7nf7kb?g7eO< z4ATf8Nx>do%_4g?YV@*rYLfs|X|}yFkWiJ{!!C6fglGSPC%fG!RR~m$6ThHIGCt{3s ztm8QfXsH}Nxnx98Hb{XGq=>N+{CM^f52vz|1zK8%jZdkT{yr!%V2;E8dUn4=kchGi zySD^??JO+Ey0=|7Um`CKARYh!1Wx`8*ZLqI2uUoc>93CD|VCt-HpyUegY z-**5@%5~cOO}?n6M|XpqU81xD|5!m>$pNo&zRg_zQre6IP~X4whV7YsCZKGGHbR*p zRkFD{EL7!$1#Pmv3AE@tQ0w&%51ghd3%e+(MtQUZtx|uJ?kYNDk+zJO`#?q<3=giV z7fYpG_PK^!_GaoD*I_y0WHkkK=Ii+(t8E-9ESZj4uDzpxSVhKqFO; zH4FbNP=MQh_z2ELH=0i>itl#3w)(K2w*YUxAZXXD29TLX#>o$%NMA!LE@r3M2xTS3qk{nI{q&!DXw?S#_x; zQvX>mp;6o8Uw9)ri>7h8r#%f~j!{$4Q`R?)?iQ1=wFDzqD2@&eQPku>CmB~lK|*}{ zXqa%TGSR0i7|9r5so1+TxG6bq^zH1;*RQg}WOC;~VvJTM`cjgAMjbbI?y>hEk1H`F z3~Lr|*Mt!j&QaEG>WH%2IY$(3bc!FZ3W1XH&@73cdv^3TtPQB!^0kSkjMvKmA&Qf{ zkZrm*JZHNtgQN^aJ^+Y$(Agmu)X5y#oAS4*HR5Qr>k`K6tFP~Eqpx^6_tbLiQZ$)> zq$`oW%?x*EQkM}gvC82$sB&^TTAtVmAyI@D063>#X(4!XlGdxSqjTwIzQweR znR=|RAt}+4F|;FN1B`T-XGjJNDA=y+GD)oW{hAtB0rCip@7GI_T z`D(oV&;*QFOLO?I@0!#oCKG%{0QPw&b44xyh0Lv;+GPD{qy59OG9ON$8``k8JYiZ45oJ-9T)xXikgNq5rz`cw_8 z^*oAx9_9uD04|sUQe>Z+>mk*17^)hq%PLH0wxG1qU6w5S{y64zsAwObS{>JQNk-D{ z*7E5LW`6t_#Sg?puTmsJl*Rx>3n2C&hsLrpL9lQ^DU63bGCA9_O40IMaJTa5{uVTY zB;q@iWm$t(C6mEGW9KeKXNgE(CZ{unlj_J^Drd2ov1&qe>D)x>_wNSdEhzF8*@>>w zt51Rdi#K;;j8A6_khuMAQkl;kaPadOcGajg6aQQ#3*D%HI*g8NNb)E#N?CTULcqpN zjSaK6puJhFEB{Y2TkZj*t(zikPL&5XJZ*siw?P$!rm!Z_sI(ftroiD+E2t3m%D7q2 z>#$9VQN3N^NFd#$hfBCvU(2P@}FCm?t(*zq`=nv!3 zU2K+%N-zVNB-Ca7ATbw(n&g0JIZEb!;eK9hmHR8g+WpphD*yFc*7fscgZ_7AdSz&O z2j?PU$Ngz+IAE_HLH`HgVF!xiv(&BX;~mFZmQIa+pieX24Qp1-&Q50+iRRmA8-UpH zMokFf%^HCpsgDKz{+HU=-lLYh_v6BWr$v6*)5Q^U_Rs|<5D9I`gV)l1rLyqo!w-b` zgQLXR2HTa!#DNcNXJaCS6%)r zOjM5lIHvC=Btr?C5;#adi)R=V$lE^hYKTc$C9bnZ5et3@Zw#_ETCyzLwr$(CZrR2y+qP}nwq140HgDNBr`~JL>+Xq|i1Y94ohQHj zMdZ$txpFPR-L6y@i3T`YvRlNJ8(s_$0_U3_T?=SU!TeVh*oX>86*DzAUjgafZ7+}< zS#9qr<+>H`ZVHI0Rz|}YZM}kt!5LaVSeazRUljTq$xcp+ac^3-Q}}prf0DMw=n3KO zI7TJd7jgWy>f=1uv5)`-1Nyed!L>C%?6m*~3^D~o4u~-!UFlBCsGzG6g{#-Tr?|OY zz21_~tQT@w6QU-WlvzN^x|bJ-;cEH-2~&J1YVIVr6a=_cN++ z$C5KW2Aa-(YL<`fzU?m;FSD#kPvAG|lPDO$fUhJni(IJ{P{Y$p6kISIvTdmn&4XV< z=A2Q5V6PzL0C^z^AUDIV8znGJFuWSGVdjYxb}A`cOHMQW6gR`O_Wo+MG$YvwKQ8)_ z9&_I8gl-h=b|Hf#X+4HL9sGjaCb{*+=`4e{F~=^ZK2AK*F>t9p5f*_nE-#ia#eYQw z*1u718drp50`y-Km(m4MJx|J#k*72DvuGX>)4oJQOvWXffG_lZ1a@7645rY)klbWc*(HY`tEu z%%4Fpb7(i}QO`|(o6Y8i(A_8uz9w`CD!kAG(3G?cDdfu0=jW>*4=m8S|3F`$a?dk@ zofyd_7YZv6nEdiKXI!sldhOE`^pR76@#jtyq>KgQaXf0ep6-e+6 zP3W=976f=2t@Ghf07S(hV1q%e`zWUzhgxQyJhdrdt6H14Z_Q}oihZb}8HHz3gZRTP zW=OL@;uj3UD?QPNPf*I8?6{ z2^bmI`va*hako&vPzyt4KU3k(UZU4+w%Xw<{5Hc!zL`hhNf@AMyvJl>;j6po^wx_A zdCWHJ4UaAr7n~mDEXDkraiK0C2;sccgD1wgj`F7!{l`m0-nsfPN)ANja(sdM)^ADA zv4VCf@!DnG)vG#G$RgsxyJ`n*9rPhHZ8Eym#Fg~y(QX(ai2&Yur>~tB8t9Wb(?ZK; ze#ij+L0}>YSj0`NNuA3FTA(ma`&fU!jmH_Wa(8>f`ASwmulzf;4(x2Yd+E?Po${s=Yk=Fpf^zoYD7je&_!(bg& z#T`$oZgZ22U6N>GMBPQdi-GuRY8@lvixH%hkJ)^z;!|BMdSl~(5iR|b(?}t!*T-em- zuwS)`RKbo3z|?kf(SZZ61>?HLJJ78rqy`dDxaJfb?o7c}rd%|!U{EtlnM_wdCWL#V zv^%+!PeZ;6th5F-{7DY&G{~(yBLAfN1gnLI|ACJQ)F_|dF&-Y0Zx8`Sg{ZVV$K9qN z5bU=;FA`>*rAgl}`fchwKHfBK@Ch_g5ovtzk2Cph8BuBXQT1|50T&|s+JhKjf(ws9 zQ01o%4*R*kf3u;Ur|7DX0O8RJnWS;(h2lmfgI=P0&g9E-1($Q&$p@l*9&L^l&lvK* zhOd~7q@_vbQ@9T~=a90(du?~bL}z??@uu=X&7M#bpuBBfZ-+~_K>?BIt7ODN9p@|& zc|9Uj8MesjAbeA`i1=a$wyOZvvwTN9q!Xvc*bMn5sOgHIS)bqChJ`Lp!42De=CV%R z6UwAEita4Uc<@ImxGFZZI$sE<|KKoVFn9^4UZbfF((9oSPRuicx+ zRvugSjLL5IzEb^2-wt3ZhkyBl(hvH{F(?c3tF6&Xae<2YG2Ru{HOhOUVfAl8>ini_Jp6tc^=`V4wat+E;^t1sQ?uy6w)Id^KvKqE7b#@VDF0n#BU;hcihCQ-=pWf zMFO=%LFqRpaCG$0Q^_~+s}Q&lboV2l96@)r5A6{*`iTd^`%}Z;kh_(T(tsNAdre!r zuiU3gLXuy9Io7iDOj=e=&+7*OnNODa-U!YH;_uOWW+l-y0CTMbjJVTqY8ik?M6;mM zxFl8deXT3gNi4ZZnybm{zrVmYI5!RD)5`XDdCes_Ss6=zUX4Q}4Pc!dX0UIIb3~-M z7eW$lO3!Cv;A9%~z+vP0rt(!id%Yin;Ug$2R>iE(xy&uDW z9D@Fuz0PTxVA-jhib-*YRT3Trrcb_i$7AU%R0UgClLws3k{3!rE`})%p4!E;u?`~U z3xr&=Fx6DtjmJL>_^|dp`dfypYz91Eqz0qFsSmbC-La1M7Jmr=6k4EvOtBFpyY z4w;mMD)aKriwrK!LSJw-rvJhRjTwod z?Mic&dk&AJAvS0tKw*>6`}5wEoXL~QVnuB~nRRcISxMZVtTJLy+Y_G9Sw@@hLkAUN zUVbXQgbPq_>_27*UY-(|Y`XjNgLHto&Huu*!yGG)kJbyVX~e}erL5bo_4|v};NGWx z7ah8dXX78-JbHk+t^cTmfdBrgudSnPvgwUlX9yoa^V4q8dUtu-2v#qz{VVGuFzc60 z?&Sn#8o7-XD$B-ggBhJ^*mls>`vX>0HBURDhLtA$yYX8tKNnMs9m`igM1GkkURVgp z9smF}NiehPUy3LINGRHuegadZ0Z(1v1?=}E(<|Ux{`fS05!gmqu$=S zgtH^a{iA(jA!l4>S4nH~ufw`_6f1Q`yJJ|!57(o-`JrB&l7QUp>vY_GRWbLGtJDIX zReoO#Sp;yV-%n0=%?KhK9oCw!@`llxJ=8tU8<32Ms0oX~80d>55+K%`j7<;%i5TlU zerRVd!Nb`fb=S4Yf6tuaGh$bF{(;(41_u(k6X78ZGNdYc8c#48waUo}Z!G5w zFW+8;nKF+Ja`8daxUeZLTQeZ*bN8+Z8PKWM-3h4uqYQx}p+fJGLk8EzxT`cox+Uix zH~(}o*{g8gtfrJqDf}yczm?2^?RoX`gn?a7F6LIJWHp29WL#!0Q%bH7C;%z9rSL9^ zW!fbZB5mdPbBJAmEsb)fl$61NZ;vFlZU}G`qma@a zVFcX#4-#nkClnyDkt-xyy$W6>=-a1O)Wbp7wF7o}&I#k^8><&`G6 zyW26jQS@%r(Z&FLd;Z9)0~2+f2{;4&>vCNQr4edTNQ*R$_lxQc{dm))xY$zHdbd5e zzOj#_Xul0eUsh&X)~2Wd6c2RhZ;dDU$Nx(3OI#uyuX4JIPRp#_L|(Bc&^xYzIyw_= zm2_p>>P4htCWow8K&}}@_O-+IR?_7;c9O>*^UpEzrDv*~QT6Y-V$}l0rNE<-k??^k z6|9|Vr&1277488&Dh?d??!XxEP#c~_>4#r&61Q{n^Vpt2o%iq%hMN^ zeM>#ZM%j%U3A45mZjw~xPW(iL0dYO+IGPF`6k&k)5$!!q<;!@Jucr;tajH667#}-Y zF6BCJL`{kuHOgNG?Q(I_Hy5#n=|!tNj79G=L-0E%@pPeITLFA9w=ZZKmizJg z4;fB+=<;w1HJh)aZC+c*W}lX!)gKD%0*p<~TY}F#?=xp7auRXjm5hr#)XW$`Y+W^} z(?ngRdqLucM!{8TXpgN&&18c=BbC4f8Ugt6T^>r=(iR>5#=APjJoG!7K3^6UW8fy2 zckdK|Mpj)p9R~5J_&UXa_&Xp7s9>mu$<-I z+G0rD;9%<`!oD(4X|d&WiS~vc9$3XQLh`H0Smq@3iD{qkwG5)PN=h3m_0W}7Z40xv zA4O*r1E;WYme6gta9NEo(h5;gQ?Ys&tQ%i`ID=6@K?p!nQ}@GXT>z z!uz@oME5Jn{6(X)$)&J)+J&b$p*pkQJ&Q-z-#1r{2rY-unum3;oqQ-(M)D3p4~X-s z2nT(!8TFD^Ea-2NVCZvN>?#dFd%FhvsX|?hos;SP35Sz-ltQV&yEHBe(>zqdvLq)# z@rQ@gv|dmCumi)Aj=GY=fC>d!eMLCOCh{U$8|)<2I0WQ#3H?=Hmw#8$%6)_Ek@W#k zRL+}WV7pT>mld5p9yefpM3p#}S(Y1MuH*?Zi6l6H2hUE6guMe2R2J7Pays~8qA8iT z`QN<|a299x5mA8iAthVI?K4jUW@k82TteHbws6=kb1^uq3>ub?GGv0bVfYbiLYjP; zq?5ifg{Y~$|9oEYM7F8(gSH^FF}brE@oax8V;%#w!MY4?P9$a;fQEa-Jz^@X$n1*y zxQ@W}!_|cC5$)hvrtWM3<9vv%|8DQjCFSm-@eQW!W)?Rb4SJz-N+)kf@oRAbXvF{f z&P%21%DdbRgEWLlM)BE>IfW+?4OgPx{#Vwf2mH`#tO41>6&d7O@kTmMni@Wzvt%}s zcg`i@VeiXRW3_07>!`y)X!j4xa$eK;*?oKAeRIRgT-ol_qq7^{+qs9+mo&ixt9eqw zys9uu6WIl_M~#r`@_LnZ%IjVGGXXkr!3*`~VkNh%vr&P(gJE!oju*lCgyZwPn}tIW zVE$=pJlPUo7OE|ML-!#4MV*`>80=BH$R#P`$u*_I%2B#z>?5!;_-wd!Y)W)>F(8x8 zbPCM)O6V`z#CxVCQp}%>1()(naVOz@XoW$-ZQ^Xsj%j8Q;JePSlVrhd7hQRcaU=#Yh953`f62*V>rBkV62-|x&j`=JB zi*+Jh4FbQzfji?qQ%AW&;xJ-IG_S!1ur=KM;#lG`y^Rc5U=!ntcB-Vn3`%~{Kc2!k zbIAgI3~%l*UtXqJ1ohd*kB&vNJlL~uI$N;^bsStq5<5eG=SWftPfxWQ8{xS<-i;#P z5RWuI^<&!`Q5&eY17MJOD7+^Ls`-Tqj~@7qgo>KgU9)Z4cYS*3yzvND{zGg~*pHu& zYMdQQFxeb0{@sb1ptiL};Zvb_9vSATU=&TxU1&3PBjzYeye3M!LDLC-K9CPdLJ}>q)<*jn> zHEiLel3kih_KUbBaEHb{%60aSWa2<(zlUev{niUrs*N6~lJx#>Au&CWCMk(oJ_Hyh zQb=+NyDw&hR;kY>(h|@$_tAb+w|iN(9Vv>XIjn9GoK3;T`JhQqKQWFDFNnZk2-FEg zcXN*k+>+YLZB}XS(iYC|?Vbn47Ym&A6HTEzKsspwZSc11BHzf)tXe&`s1hwjxR?eR zpHjb=7bVNHbV~qgTy{4l&eWrW-7M8J)ZJH&aZ0nn@>|&HsA(od5?A2FWXiY8EN>pN z?G40@)T2v=h^ijK1P2d&i%sS{<5D|Dzr<+wChTy`yvW38x+`M~ z(%XWx?M3omCn9PemZgu`@I*^ndGEgbvYp`)ZOAUYVb)UQb7SU&2m2;3TVZ}~&yv`i zqvAMgn16$F?w01JXH8iM@(Ri2J7lNk)f|pWizc_LcWVICwFqj3PfRZ&_83XCeZcsp ziOk{7+)$1EK=lj@=3%l^9a8Dq-??9^ZV{jYigBq;*3SKny1WC;BKc6IjO!Uw0)T(P z5yow8R!`}Aq_%%oh2(~Q)IFPlBUf>+@oJ*FtQU`P$*`2gyfFS`NE>8jOfZ3!DI#*u z#;qHAeEu9A)XVew-NptjHbM~sFjqJM9v(96!excK50Bk`cU1?dFsm38zz8Y2;C0?8 zT6r}nJYt9#-=B+-ePxuk6r5fA^_>7=# ze1IVHT9|hG<8}xnYSJVb{U5^w!a+Quj#6p3v2nA&nf8j81Z-MEC=+M7RlBJ^9r9pV zs8dF@^DJ4&E94k^ynlwTsDN1(0_vC8(ivY)`Qe%=|CVH|X{l&}RmPeQbp4=1vy3u~ z01kP;`5>?D8BM8f8aLHFSHHR-HSt&aJfO0fALnN?!Ovfuiksep2H8t8*ctQ}B#>8e zE3|)W>RYAQt!uEroeBDYQl}^X+Gov!Mq%1T-=AzDJ$DFO8VYMuw0^zukK;PMNr_`u z%}yzp>}-kh2^ zNM24U?&ud-k5?xW+mNNpDJ;N+#d01+R=O-AR3QzhTBEWlMkznpbWT)Laeu#ZG=Jur zwcF|31*V=1;Hp2GWOyxZVBg=+T{**9PSOtZ)zL_9Vw5cm26R4Y;QW}`M%- zeQ+EsQDs$v0*m6MNZi$4bh}@AMZlk$sm9KC7-%c3r)$sV8X=+t2_ zWD&>|>|9li_hd6yztn9E(j3u@u9@#@uR84cpo+x}?K{GAYamhTg6#ZSzH)_uI6XLb zjz5w_D-3XH^SB|mR3f*-XABtEO6-=x;hg^Hzp2=OK*B<6UP2bGpEp2vQ=i1VjCvel zG3^ku_y%}096qzteaWGJv`)O3UtPtWb+t%d7|=}I$1r5s-cL=M%+A=P{`$~#UZg&u zsyc4d=AtE&jd5HvR4MV>WX-7**A50>=%dBcFbo=q6NgZV6|T7Be;oANNKW@|j*namlBG*9MztUpG%mqj%+VJ78uaxDfm`vaOuhZF=Mt(RH{kf&g+-g)k?x&2^!_nhp+Ma`7 zo-<|RSr$~KL^>u>j;U0toxZYv3%VT)pG;-!-G$fP6$K7B5~p*t?CQjSrOBPp8t`o= z%J^xaA68z%)GuhHY8OX-2#9>7>;-mB8D`s;<5I$;FlS$-(xqJ5%ZPJ+N?aV(vRbu7 z5&&5Q#;;iF$tz)%8fwce41mpf=vZYX0K*Gwz>n#3I^zUoZNz@xu3$zJECZVBaYXIGflb# zt%VNnx$`tiw&(-y<*j;_FMxG35Pp|wV_m#2M?xJ4van`Tf9qOeq6J_6jStt;fz>Y6 zHV0I^pN?iD!MZ!8cF` zwa%Hyhd};wC81cf^=f%kN{nJPLLvRlpkj=L>rzUklhOrn*w04)VFAaO@Gwo*mF;3j z;Xw>WN;3T2_6F8~?1fO#y<}qtGo^&Thf|erCp?&StbwO6fCxhhzHF2&XyZ6klQ$+k zb}{;z(PkXf7_42ulN8Ov?HGksjoNEbi=jL1URX5{({qK@;mcfW0Z@x7V?iYYza12D z{~CAOj~F%al+P_q(T1*|R&BZ&5sp}{k?mrt=c8k)(io(?gLzw#c0Y~ukhRmU0B`kG zud!9yA@~qzald=n>|SXT%~K!JtHcVU9Vu`C+#>l`fetX1K@X|N6XjH!s~$B|+u-^n zH2gtYiG`XnRV7epafFh%^mc|Xf_=|?d8p+~I=x=gy&7}!DnLb|(ANPaQ-v)0mfMzA z(0WW^YiP8gtXg(G9*zZ%Ed__uwb*Q7;L#RhU>i5MJHK8X1t5oY7;x6FK>VObgUpfp zc}64H=z;z7h5yDaNpN?F6IK|HWJ}t&YpGcGR!|CDE`z9@>QL!>e~)<6KQ;uT@` z6D7LPLS)rq^G7V002NuLD{u9LfNFPWz-5GGL=`NboW;sA3QHawpAEZz@8E-uDx0uCI47WPrxGIvMj^r3w~bci9A zAD)JXz)D+}tVvQ*TH;!ML(Rzk-7nG1QF^92+$k72W7K;*7x1JD4@pOSQBU98dS}H~ zsXruFSjvzwxs~F7i#dIbd1M;!VSZ&tZesE%*gh-J^qNr&uog+A9peKeLVX@sUDo3O zo*tlF&o#+slI)ato!4)8pRpmaoNUIHT=V;|GE(LR@92$m{OhV0M<3*C zF*c)-}bW}`Ma!qBJMU`Y*KpGHqy`PtP)kDv)>&(X`md>I1 zv8^g}BZ+&aRnAA_N*@OMaK~nFbg4#QPbcwJp54n#q8a{Aj5M=4P}8#MTe?jac}6f` zREkDvWsI!6O4aTNZ?W70kMOzS`BE#NGp`-X857g{jVS6Vn7C}voT(|6mdvB1-^75y z6l&XHk>(&O(V?Jt1d4!c0AVD`b<@Z zd-{Po(#n2~jcywB3-&#M?_R=zt6_pWCscuYcWO3FVop9OTNP>7#eMZ$CK0fCfwXxG zzXcGFJvcQkCOp%Pj-S$RykPG7zgMRL*Ms8iBq91&d|nMXg9ccwxXi);K(d z`f?3omAQ0!9Gf>WKiRa`MHQQ%ZZ4B4%bkKzi>gtR*iiZJW!b`8lUxX-Qk2qnC322n z)HD7#r45+-`adez7{PHy;Id3Wf7vlGlmTzB;eqAW{l;oG%N4!wZ`^N* zmT%~iHfV71c7AzZ6{IktFFop$iGA0o&l2Lp|UcK zq>~|Mk*9T&j3!-E(k{s)bZDaQ1Qdk$_qeTO;h2wiAe6xGn+kx(3Gy4VPIZGdtuKI? zZ~$A=`Q)D>ItY(o=I*~%xS{PZZ-f!mY4XU+<&aD|DaS=nxJC+@d}ubhsYR0(KMXi8 zosM-ofgNW{j^B2_KOjCCF|Z*zi#C%ZG;R+0TDXTvFcP6mWvg}X9qVQW-MNo_S8!esi0Uldw1XusyyQpOr77-&X%@Pi?_2U8h<5i#Z%uH9D){DFaiaY=s32Z_tWy4IzhcA7xD}Nqwvk(3Q33);UhHm4j2n8h}daaTI0(3ZoVp@u0% zakG;yqRjZ;XFgGr*M1q{*G()_yvF$#s!KJvp&>~J zDHK~y>vehz+B=oAFbrIt><7nXvn`P1IqMa|D9vj|ryOIU3h}5h*9nDwQCM9$x9>oq z1xG2C;P2q~?mP-KgU;QptowyRB*~K&CAM0Je;{cZ>J_7c1S(`&F^B>c-3IC{v|0{}bWMD+;56pS z@V`;}k{vgAB5Le|hu;b5L?K6=&W+suJ31XgSzfPMTnBLU8< zOVp~=h>^b>Wa!pAI!$154%KXkSeYiCs<6!>?So$(Uoj-G&@_`=qBTFB9CmIG8obQm z{B>(9hs!nsqr&t)KMkHjGMqWVKsuLr86$42%|?^Hl+9wBtx(dmS8v)-FAYSezCn-VnAne9_hF5 z7EE2ffv0*ZnG#^#W!1((5v5X%DixV1`4t)x>Y=nFc-q+vPr((3C>R@u)t(y~Wad96 zZ+RMLEsH`>-mHd2sYzDE01CR!inSLndW9lxGQi$2Y@}zZPKV>S(xN>%r}Su}!7hTu zX1)xqfG**;K5I-q!mPoto^-!9BS_p#oXnm{`c{m2@P-qvy>w!;QfEgT4ni1vA3b#F zp5=)Y(!qKZcSeL%TI&Bx!LVS(_1enLO1C_DQ3Z-EzFR}+&Yb;T(*}rUpLlSbT=%m! zxLho-d!=SC!mn^L)#Zwg;=-3`@I@@M6Gw;xcN}ZYDOEk&2V4AXq|Tg6(0=fw#jK`I zSKO0l1R=K*gNFs1KB~6S5uzB`x#(O6z)6KGASv%pT(A2c&9hpZnA#iS?N3mW7R zZ;^OW7=0-Ii^psG7#4@K)c|HC(Ks;~RsMM{1||`q0dqx2V=Jr?t;&R>{`dt52ij)k zh1D)KvO>1+#~dGE4)6bnp=iCrh?`U!02-$9R?OJZEV&LkK|F|XrMKyLd(A7Xk%9ei zrGeB%*kJ@e7Dxbd`2RCX{wF@#-|COIB2gmB7u0Mngsb4sx--EHl79_+0KfoY+};B0 z_7mFpVnT&X0tobA+xnTTJ*lxnq;tAXg(UQEFn}1Yz~)_`cK7`r2J}~7)4K`iqpS3S z%Vmbo@|%g|{#H%0^euE(?B0&?5gchAm}aQmmOvD>2_tVeizMT)TF}^~C@ULV(CnR! zpODg^q$$w5y}Ta?N`cDXmhKLfs4$OPr=CUDugWZLlAPEetp{JjSVUV#R=1ifChty7 zyVX@ZYf%Z+2T#g7ebMyy=$Na7p|DL{CiIS(C@4Y1V70$r^D~@wq4SsP7|W?rdgA>U z^?#n0RWL{B|M{9AEVMu@^FO{uD=B_TW^6I{Gyp;plEaYhKO3n4a}56H3mL4(zKS;j zpK|$*Wf#1%2Ee_4fe!mw{d4$6{~w1BVIr7e{;!7*pG8?OAZV<-y&$k}3REKdCzOA(tF^ z4(VRfemzoQCAlQ0;|XF%h;@z#59&SI{<1CW*ArKV#6oS_#?d;$VXXsUFJ}ZlgM@dj z?*+?{tij0N38voL2k&*DOMV7if2yzHKwIuZmdC819oj2ev-OpkMT2JS4idmCWrB@( zb|jl69y`nY8+xGl#9kNoE=h zBP_5&H7Rpg0h4jP1Yv$#Z|)eeJ)}`UOJm^K>&jmvGp-uix;-Bi9CF)&L)y#wS*?!$ z5Rv!Z-UcYnnG$50#$hGUWl^nGjg(erk zioZ~|C%m6QEuOY>_@YwGxtiFYMep}F{MEg3{daITE-=tv<5qHcMYy{rZ_6iYAE7}o zI$E3*Tzb98Y%$UUFKxpC8Y>@@1dvZ2?OQPP=!_*3ltm=IGA7#NYy%zh$O;Yb^UKs6IjYYmgmrtEI-m|S}Q53eQS?>d*r9-f?>9#kazS} z5b6{6MW+l9x8SEq#+=j0NFNB|9sq25uZnSqUlIOX7z9ZtPU0XsGa5b!V`#Hb@Um_H zc1qqjqe;D;M$Mkfdb8PfHFh1TNTo2NzI%nrfn$~~hAK`aoE6C-+qU&?cpi}M>>jpQ z#E`?_voBiEIn*qKqoG6TCxT=&tueL&wL~|v*Q_K25igOUdc)$c=$Y3ayf8v#gZubO zT!8S451N4n&#i_qyYVF47As;iQQuOF!r}*0cjw>5rJmg3H^6pgZ(fV2ANfmU*YO&N z!(URF^2A-r)}`B_qU7gZWwaG|mj0JZ9V;R1EG2f5n;`<_Gd4|~Y|DoK7zx@rqUQ?` zYVYlDqgNRww|QXd{&~WC9|+<1(J3+NkR$Vx6KS+4(#v|jLMTlbHt?;PRcLWUz%PF^ zgPVE*yoC&2?A2SrFM8Hlp!{4gY2%*ee_9jaTkJ08nZoz+qDm*tT+-r#;a|~#ARxkn?HvL0z&cHvp?)q7l87D z-IH2C0};5acT8_6ews1z9cA;fV`Zqj$_oZ$3cf?QB5owRa+w0zZp+-bn;QDUWKnq^ zWduj~DH9oEI&m&Gc0*|CKqn^yUyNjC`!)!X9e1%;Se#FkgnSl|tcfi81x1xCR5wI6-%N^TOWxioRpp>-I7Ma?~D1!Xv{P!feO}XV!6A zq#NRT?Kyt7M<=RxVY?R!l`)6VaMVqGqFKXcALrITMm&P@}Nifs?tNE@aZ@RzOMH<#rLTcYe7fRJT2q= zS_MwMB@2kV8UT685}fSv@+e2}%A!1F9GO!}|q9Lr;vHLKg5+ocF|*n7J63_p~f&V0_ISQW#y ze0{1BS8L`Zp#~T=55)K1R`p*B1rnWfN<$o4RYniB>5??%r>X}pX6@~@!+%4gj!w1@ zbd0%S6N(2D4^~@wuI=|;(y(2Yni^iUFoCGwWudQUhC(p~(x7#Kw~9MHX5K9>wsOFj zz3wv-a4nC8VGf3+V#1>QI-a3*qga;4efMXkSkw68Id9segr?4PpfBHBNSa{o~%Sgwj6 zs%_t@zKDZ6j!L-n_<&Ki(@jW!Vjy3dt&$gagfpCW^N zTzlS8Lw<8?S0x}VS6);50&l&^_0QE7hB_sT&$)4??h73I9^4_%jxGqK70A?3bag;b zcSwL(I)&OLsL8L0>SE}23!7phq7$!uy?n@$P7I*Ia1qy)aphHX8Tf9a*sm;#)gES% zP>xy;Cg-HinJy@oJs_?YI{0oo2_cLB-M#-+5i1rI!`fY4(Y9=*x6`~8Ps@|EqPhSv zNG86V;WqJ90Knl&&8kKVY;RKg{--Pv`o$cCsgJyEYNm-2!?aK+WhtwQ%=CTu8E#W` zB%AhAx%#w{+tP0GR~0P5flCXP+AA!>~rnyo#N&=7Jg}p}?zYZ_jY_#LCErU?3+8`kZ z^3n?lz?uCmrga-U@MO>j!P0@)oONzCDmR|v$TYzT*I(H|P{^Li@Sv-m^OztQy=ATt zwu|x2%&&k}#G6@s<2DNIy)PnrM52otP*VOkvmplsbJuPmCFS9lhQ}TD=6g*s8w<>HA8jSsv$_eC-FQ0n5s!0PA|v$F5x|`8!3=GTKsP6 zT{RS*#H_*xP1}~J`mR`B3T{jGMl5k`mWXVOFmGOnAKKYmeiYAb4S$~HD_3`6D4XHY z3eC*K`*|bHuK`y5?vVtwjdr-kEb=SrS~*FO%Vz_~$((1rg_uFVM-A?&!~X0})HW^U z8T&zOB~BH^VkF7bFwX4Zc@$B&Z#&HL=HuxVFA1K0Yqoq%SzXr$QSYJvnxs^=7L}XE z;S9YLVkI>2$yAh~Vc;Ga#0X^@kbHcNb8AQ1WipqQwhqu%SSzY9fo^EFzoWCW>(apt zxX*)hmxi(dhHqatMnUGtWIn(Qdt-mf#Jw*PC(=BXvkB-W6Kb^jyeUko+s?@9ah!zYjjE-x;caBm8Ithi9!AN6Kgc$l1pvDD-rX$bhiiH4$3J@TmMBaV z!iu0|WIhJmBZ%C9|7MDFU4@0fuH5O_?l%o{ z5pz#N8#Qof^DI&t)ytPV9x5-`e!luJEDz8{mcbL8EkYZk=`E`$tX>lK)X{RodG$<+ zjK%VafAjMabf7y!0}1ldw+jNzvfvKO7f8Zg5d?zF%mb$_uqels!P7hKKi}B{>J;4n z?T3)edIw}V)GSb}G^8yn7mrk*>t@rFURH8MocJCm>=4NFVcjnt6c3?2zF6rsT#$g3s%P+q26ZD9=#e+pT{n zY=dX`a-jgH72^1|X9jRMpgH&2=yo|PXdtQB`j8hI+vKsV%~-L7afV_ENqr45fs_p) zp=HI}>{;*e=B3iZG3v+P_0Fi@_ z;=O%kil+(Ds%KF$&IE`1(?1k@SsW)sw9@R{<)iPxC8-Vr@R}#_LGsu)3trn!`8r{BGEzdLvuo*@L4?eW%JEt*@>ic%UQbk~}XEmoy`I!53YSLsfoQ8ChoY z%r->Ll2i+wv$TF6BnxbbdUvf@#QqW@BbmbEk0ue!AL*le{!ACn@`Z>!FaF_`Pb|aS zQG5)3o^$?h{X0ixmPB!WLP6h@NC*Qyu3KY}EWp6{21!2C>f~GZthYkrQnvCbLuuar z0U8hZEaHIHOiZi5KfFg6xC_~ty`NwJO?|gRs?@D7A&O>W@UBFvpD2`u;333{nvNfTNow++k}2l zn3e+$+3xQ>*%0veWrXfEm>OGnJT?%X57xB$Cm7=WI#g)_Z%aFzlUeyqoy)}{I*?ks zl%&)6=upzo^=e!h**?EGwxizjE;(lI~UzP%~*H{`6CwrPS%fE zN&qvV$GW5T(*IWPw8JPOwK0;Be3=xjgzIzn%A(%IP!-E|J6c{%!g?o&v3OQPL;J3> zgpLF`9w0)8gdc|cUJ14o8lYRZ8bl{NnSa(&CN+T3?GnjA*zgIlP21vSzy(xi)X(Nm zV(fZ{xP)QSJpzuwLk@>X zkxt%}{m}QHu3k0M-2KvpJ!a>B{3P@IHY_Lj6H#es@%b7A%^Qo0mM`PtP26zqIz%N# z3Qg>(BOCOtbT2A*bbRJS&08>rts(BLFtt*i5mW4S0_O;bFmcV=ky)k)!D_!D z0Vit3Tq5Sms{*PV2h?jCnMC^l0&_P3gQn+5$L`cuN#B*79H6|vZmzsERS*D^i6}@5 zWax$6Sv2R$5#r6%14Dy)Yr0(x6gNS*@|&_>g`fMR`_`|SO=07OE#Yr9xsUoKb(S}; z4z2;q7byrC^My23HmZ3t9-vp0#(Gp3c@vYF$_glmeUT9OdXvm8OAYL(sdJ(8GA)MG+~?uDk7^XHJ1;V{DR|3V)MXxmpZrGk zpR&IHOv3&_=%CQ3Dq}X{y+kj|PzM-wzyE=bU3lcj?5hJu+gsv9VE#7MelbYThBpkt zlMLX=lDV2ky}MHLE@ro=#&29*tUG8-^Tgyu`;YWa_TS}s;g&v)^z@A~+;r+f9UL7x z+Q6~R*TO6r*ZAr~>qH{Igf7c@50df`>M~Jvl5gOrFQifLa1bnnDD)+xmcu1Y%mBr> zXaar=(*C;~FOV0#Q{;cI9-=~Gaic8|Ae>TM}ppP*iWHEmXTv6Iq!k^3t2yvn(8)>mGOv&+Uz`@z}tYBv(#Q`@Xx%DoJ) zH3mZ?bPZLzjjf(rwRr@89%@CSRT<_5N7Ec=og2cRewRh%N@X<0)+tF5uvKM&q7DCRs{ z;YpmOmEBs^aEtx1p%#qcDKD{j{D$pj?gC@WnHieoMkL}SeAdXQ9+YiUVFzLZ&g>xU zd@@O1mu^?kbOsAOx_bf@s>Z`zxnP3k-Byf%*Pge)VZZ(@pWLtl23!xaBz~LQib$zk z*8*>?plK{ofxSGaMEc6z-$UDdgTygwX{J915}*3isaD4~^s;W}#CF65uU^fADxcQO zK}ntKK~i=>0TPLp(Gv$(v7Okoaw{ zmQjK#qoe!Ug1e7=5GxR~dl7BO@YdI*7?85IO7*;#3f&zT+MdnCVjef3ZrKXMTY)gh5;0#F)>^fK-UQB6P^cDKD|X^r;*0wXJVxy}a+| zdh`@^T8+igXXsIksPv*P&m`qSkKyM{v88i`f~E|QywFvo)u;6}iW0KxIIH5Cvu|-V ze6t7kObkBs}kmqyoulf0*Dl zvXqzv!IIJ?b}0bk-j?5g-lB-VB=T`BZ`^J@givQvO55!~&DthQftjLM%D5vOqoYEs zFZ!#p{f;H5hb~>XiU>2JC55B1XPFE7)W;XnZ(2Z>&K0MnwKIhIM&w~oO;9jY=vw`C z=uy%OTO3CZyX8FNj+48sBa`&9^M$^}w+n1O_^xCh;(CM?@)x zC?VOQuUYkg%!Nk@Mq^huyPKs5j@Sl22f-h9wuTYjlZGhE8u?>1_^UFg!< z$rQaA@Md(jjzPqv?3XlNrro=Iuy;~bxi2^|M=ay!nv|kKs!~JdykENI675(TGE^9CNG0;#W`A`R9Wt8C~LQ0WM zEN7ZlV6bnN6Ub{jx z3Hphld_o17nv_yBwc@$goG=M(9DrSqhnNxHa*g|Kmx?KXX*;J=Gj&W(folWfhpGb# zv{(ilp^Q0KD4g9VsUsWI>|@3LsVcM35HJ!^n1fPumw zQ3U?*XUL+@{?imS?{Y8fX)R6T@b1Bsqj)OMbXokVTO2#YzdylS;=j1t|Krd8KYLNP z+fQ9;U?J!T$OYW2w+ONRTI?Ernj7RaDVVWDRQ)7t6=Kj9xB$nyo_2g<(Sq4?|GWtP zjkp}hbJgje!tehWN5f>TjaK6=cB~t?WJ?~V!?rPl+Jz^chJF3n!1{l4Y5&|DYEnSV zCM)zH1WoLUa)?v~hd0W}hN@X|eebsMOY^9XJAEbaC3HUfb(Xem~zc z{udq6zdY4HJ8TdZ>Of{&R2~BNy;}W|04flteqgjeo5=p1&gfse-8WouNU)wwe>)Z|7&6o;rpwZ%J0WbK*n)g6F&+*ZTdOWMpm0Aw}ACBot#k* zEujHwjhToQ{R~Wl!GgamcZ*?M7DxUgjMJiTGI{N%>yF_mH{j(IfpdCq@)(r(LK{= z_MXx3+edDK%|G;0zlEcNtlkoJYo3mzc}z;e9H`LR)6EVz{g{VHX4bPj}ZI7jqWH?@ZGu5xrBBicld%4=u32qpZiEwwBDEJ5vm` z*uQ*s&*$@IhS8tMME>Iat-W$ch6qP*t>J&Jd^25MR&4t z&uUCc-@O5O?yV24x6k?GN*hD9*4V+4#ENS?SE(*NVkT>rvO9l#Lbf1iP?{$-Z2c)s zCtat;AtA){YFt)}r2icF)kA&4SiNh9Qo4Ly3d(X8a18muA*uLrha+Fiwh z6S|!<9?5*8ZAM({nBn#m1!fQ&k{_ULUtO6nDyLR3@_ATVjQC}X*2xQ+zvT_>uNmSW z7^9jw`me&GQoV~NIJ32 zmAYZeu&7bnpUkXIh%b_k$ga7R?j7#qd6AuP+b?$Vh5Pa1#u=6^nrZ!Sz9>)6$uA8X zR2LKH_Nq|it7_DkGUx2H=;+d$!R#q#41UZL2rY*Xrv7SaA6tEbGi^f|laeQ1GJ4!b z>FQ{sur2Ed%?1|j34++{pgCUoe@)j-B^tC76Gc=0l=-bRXuY>BKs{YkA}i`lPO0cx zx-rJ%a9#W=`&*7@7;7Ie*XfuDOvLQYStc{B#~iv7 z=XWVoGB-GOot?C4^)c!Xg-l%SCPMasu)Odb_-Dqt^ zvF`Nu&8nx|3e5bWWr&7d=3@;>`LYRxZ6UW4rh66FFQgxRB4oRD-ScuE^J>TCq|i;3 zm0NSky!%`9o)t_ro=|JN^m^;_(>#wM0YN^63oi~%U#`xYWVYv6@iZ>OVEI^u|I>9oyy!>@3)W7f@P25Zw#=ae*w5(frdi;2!U616-!GwnDj z(RR^2_o7LD@zsLj({%=E=PBNP501|42z_ATYf&j!%x}uRU$Y~5WbxTm$%kn0ew@|{ zZ!6cNf=Ql%bPvylz%uTp&LmgoBA3#6HP`oL>tC#Pj$d@X%22zl^eUUF_VT_L%XYuT zSpMCiRhztmi*8Rnpv5ZnuQjVly>Ki?uyejX zY=~aSJ{|?}$fI`!+Pk_3h{{sySof2Tskay>Q@?L*Ky_}}QgcZ*DfiURuFH&0%-%Ij zVqREQ;i8Cvz01b>4Am2r3&485oa`EuJ0R}O_>#PV_X_ujR&6x&D<@Zo-8FU@ckH*3 zeRs6%P9u(=#_#I9-o`~m1SehwwcW?cIQmL5is;>EvBn3{TLkVuw`gwr z4X`H_s-`Pe`LQa7e@caYRWS6O3O}oQq2EJpM1&BQ!{G{d_;hsK2hp@ zzX6K(lnA*h+xC`;2=&wEM^cxAY6*Y2d`>u*x76(o=KYX9n5VCKi9rZq09nv!d>(KL zox|(#1sQA7v=8@g2{yY>U^RAy#xiM~NVx{H%B41#TYfrx>rmxZER>C;dqgO(F`btBM_zU(eCS_b^+O;L)@*Yr*J zua$&9{HFw!FbRmvY>DC=AJf&*fqm$P@go(dN+cab7zi2i`0^9SdOSUx5;y=`*a&_S zm~cNpWn%a{TYQ?(2Tw)Lb-Q^_8#l3D?hE**^aK8-{ipnWY5o6gKVSMh|I_nR;4X#B zZ-o3#$nR74{UPLmZcVoiGw8QIhmgTQxI5Fp9HJAk6#^q%B#lhyTLrS@j9CdVf~;Bv{~>%0Iv7WcL&&lm#z%qQI_PI2GzRj2KhUY{ zg>gv;jn4u*3BU^a;4+(qfV>AGtsIyG))#KfF-;P7WRT*9yA^RXQ7t@d^aEz07;hQ3LM6x833?HPXNvU><8LvEa3PIv3@eN z4*?Gb1OV({FNwf?6taAr8ORO*YXJ6V22g5~n9%kHVEq(;DL_fzs}1omJOXSm5dgM; zFaeDZXMuvbbU6nRnJZ@<$W)Qkl`A<|(L-ZdiqtmZ2tNWlG@()DgRxWOLlrU{CfYbT J+Su9J{tdLgt=j+q literal 0 HcmV?d00001 diff --git a/docs/src/howto/repeater_grid/repeater_grid.md b/docs/src/howto/repeater_grid/repeater_grid.md new file mode 100644 index 0000000..45169c7 --- /dev/null +++ b/docs/src/howto/repeater_grid/repeater_grid.md @@ -0,0 +1,10 @@ +# [Entanglement Generation On A Repeater Grid](@id Entanglement-Generation-On-A-Repeater-Grid) + +```@meta +DocTestSetup = quote + using QuantumSavory +end +``` + +This section provides a detailed walkthrough of how the QuantumSavory.jl can be used to simulate entanglement genearation on a network of repeaters in a square grid topology. + diff --git a/examples/repeater_grid/repeater_grid.jl b/examples/repeater_grid/repeater_grid.jl new file mode 100644 index 0000000..e8b77fb --- /dev/null +++ b/examples/repeater_grid/repeater_grid.jl @@ -0,0 +1,86 @@ +using QuantumSavory + +# For Simulation +using ResumableFunctions +using ConcurrentSim +using QuantumSavory.ProtocolZoo +using Graphs + +# For Plotting +using GLMakie +GLMakie.activate!(inline=false) +using NetworkLayout + +## Custom Predicates + +function check_nodes(net, c_node, node; low=true) + n = Int(sqrt(size(net.graph)[1])) # grid size + c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 + c_y = c_node - n*(c_x-1) + x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 + y = node - n*(x-1) + return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 +end + +# functions for picking the furthest node +function distance(n, a, b) + x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 + x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 + y1 = a - n*(x1-1) + y2 = b - n*(x2-1) + + return x1 - x2 + y1 - y2 +end + +function choose_node(net, node, arr; low=true) + grid_size = Int(sqrt(size(net.graph)[1])) + return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) +end + +## Simulation + +n = 6 + +graph = grid([n,n]) + +for i in 1:(n^2 - n + 1) # add diagonal channels + if !iszero(i%n) # no diagonal channel from last node in a row + add_edge!(graph, i, i + n + 1) + end +end + +net = RegisterNet(graph, [Register(8) for i in 1:n^2]) + +sim = get_time_tracker(net) + +for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high + @process eprot() +end + +for i in 2:(size(graph)[1] - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + @process swapper() +end + +for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() +end + +## Visualization +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) +fig = Figure(resolution=(600, 600)) +_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) + +display(fig) + +step_ts = range(0, 10, step=0.1) +record(fig, "grid_sim6x6.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify(obs) +end From 4f908006c7c2e03db7fea6dff5e84f45c8c42e34 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 11 Mar 2024 10:21:56 -0400 Subject: [PATCH 18/93] use only horizontal and vertical paths --- docs/src/howto/repeater_grid/grid_sim6x6.mp4 | Bin 169045 -> 0 bytes docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 | Bin 0 -> 166391 bytes examples/repeater_grid/repeater_grid.jl | 8 +------- 3 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 docs/src/howto/repeater_grid/grid_sim6x6.mp4 create mode 100644 docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 diff --git a/docs/src/howto/repeater_grid/grid_sim6x6.mp4 b/docs/src/howto/repeater_grid/grid_sim6x6.mp4 deleted file mode 100644 index a4ac9b2ae5e9fa6a9dfc18feddd51d34e239d8ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 169045 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%0D7m|wJ^IbMD~gyH@i!V6g;@2Q22^?nPh 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 `NIAEZB)?lISJQyFFaH1aRaje9yVg5WQ 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

+hGitrc$uJ+iH{& z4Hb6kej2r`lFR3HX_H=~kt&kHDnFR#cC6wuYCu7!OpEFxr5haYI&lX}U)-*YA}Y}h+1YAC zbM7`>*A^L{=?tzkt}O>x%{*f+-ox7;U>N{&SOeze&E2qB{vNcU5z)OFUk3@cKwfGI zN`mBrFdT(}j4dW8^9oKtSu zEgHLk!vH_Z}-6KhunBm5gbDIDObW1 zI5{FXP5-KWxjAQ+>Q!9k%O(Y^iB^g&ADuS@C|Q{Zq6S+2|F%-5QK*06CU>UKq1v8J z%EL%#%dX3MsAhoXl0hUkop27y)N7~mN_LQ0LyWvR^I}F#e0_YXxb36X{Ue4YaGur4 z3$sY6TK^DBVZ;DsW0H1{UGmi}c6eICBNjKeb)lWbNPOnD$;=rZF=-cY+&QRfpnkYy z*=`M?gK8)V|C#x(0%^>crq z47o`aT)p&6^?b#D5K8H^Tv+0uZ9nIT1GrmMwVe?SbumU)&mo`^OVRWu%5}}$^ zLUE%+>vzR0&QGs_dtV!Vmc8x5qo+s2TYHDfyTZjZ33=!yU)}V#2!A;``Q#jU0sQAFU&>I!BJ|4AC1PRoO?p+*QQJ1fC(wNe=FhwoB9K!YlVIiyWsi zTI_*4HKhZBjVa1d1Bz8Zaz zOQ)~eSLw7Be5V2H^<}4muc;?Lqd-rhtu%|}lbg|&=|}Y0$l@A4xLu-CUN|=;K(w!i zO}wFd!qjPO*=wxo5iVA8^$}{S(*8-3ba)|o9 zeV6N7=EX07$nsZUt`cHYDf8jk-uA3Q$)|YNAN*uMt-5;?lY_2ySF%uc;%eB|Ch8R# ziPh|afZE+LKdtTAU<}|n?27nJ3lQVgzHFb&)`F}pOIwZsk~D|kIw0d+UrX7R{PYIy zPoA0{SEget<%8mE^o7e1mO+o$-KcnPwZLbA0;vx|$E74(<6^jXBsQL&)bD)Da}r&c z0Pw)sItF3G`de`5gZsmJQ0S)VoZ0I*_r@kwe)30{xc>NK7K~K%KQiX;xJFL*;HjM{ zZ76AuePZ`QC7p+W7K#VDtE2F1XzIDhGM`^pG8Y<}t$NfnW;=ZYcx-rVGRW#L1N81! zsh+Xk4zhcvdEPRWFX{R;vSwg{H)zpRB%s`4kwPuc+M?J(D+1Rdu$TCJs)rT`4&a<~ zW#hQd2@=Syd#Y97Zw@IN06Vv(WDqQkbcq%p7w@_@>>* zf|vIkA5UjpthFKMeZaW+rREgw)w8OuXGIHZX^-+r48>ias;EOGVz+)l9;c`{B@^nq z-ymA7>91Q=E11|;Ec*m=Qd~6RiiB!ra>QT$!7%YfhU-u06dvVk^x2PjJ;^^4zojXNp%80_o`5VMic|m!1|h zA&0 z{A83wTs!{&1Ioj?g3-b9@qfYP5clWApH@83o(kpA>u(NEYzInRpn`b-5JZI8Xj9bR zHae{CxT`Q>OtwRE9?f1wl_Ij8n<*UkQc^%t$wP7n`aywFMzacwCa0nH5ff~MGAq;@ z-o#PwZ<%urdZ*1hpUMbIA>k?g|0)UB8{)S*;-O1u=i|3W>tA5JVU&uyr9mf z=FxoGLx}VG#8iwzmO=T}s(J(NM4$G;dp!(DO&sDs z;dbl#O(IG2$c28kUrfljYl=^urmealj=~bY|1B@PUGi)oN66r~u9gB29A(W~Lqj(S zPUu+rq-T~vJ5;}rizA%#7VH&`k>*uJxgxFMNa)79_A|8X05)7ZA_*%N4%;4sIRzk_q@C)w>>RWNl&xVsSBkCbyL{_n~gWzI7@7g7B9xhsQ zw|xKp(Qb<)%5`X6hyx5DqQHfak7OS(8scSlKz!;{8Pcwr#xjsuhVrcLOU{~aS*4|h z3slt0?k+N=&y}Wu8mx4aBi)H2#Tl^Ryo6?fBVGJhtW77VqB@v=~$6+6G3@}-#YnH;&`d9}? zfuR1;FH{WvxFtO&2ZHS}z5-6NrAIz*eeNRnsAwYs&Wk;RQDRKoBHr?i6yV=Vvf83f$O^{k76=(+4Xf*1rK;(WV3R z6)XPk!z<2Cfp98g{0~y1(7Vgw!apjLqd4B8^G$kR-x~P&WI%nYesum&_cVWMRB-ju zndEl)>=z0vtS-rrq1YLSaob%|$XYhx6j+P=6XXZ(JiOBXV`(dMoKdWjBZK&+ZUcl&0+o4wMxGfNhn$sIB@(D0eac<=;htX?NfZ6{ee**%-}`iPO` zM{mCp*U0(MwltfoJdEw6i_i}3fjO+G#b$Ctz>!?nVmNJHA`<=b<@HMDG2=6D9NI9f z*U@`hb41W_Ob&Qbmi}zL(vcs;(iAyhr1J%)>PGok$R4K)OHaN%@GNjX@hfW-C34&K zQA#{ppLBEXQx___oB>)tf?ICCb@!R^Ysjn5$jsUD&@Yl|7|-ATRy8%VE9v@(50A4n zN?7(_$ZFyNyv5arbQ<#mO&Yt^0Chpg$pThH)WKyi_>~yP@%hW(yg+g?F#(Vaqmp8J zHb~^q4fmj4by@{irFPQf7h>*xw(~?ejwFQdwY?ZBe6G`|Nwn?5&K7HaEs|GON!U|M z{-0&=A&Pn5221?~K-;4|zED5XDf5$AXpjLVW+?9M@cwR3B3Iox&eh9ljyAQBPt@RD zUciM2Rv)Zm`hr?)bPfHUc|h4Fo+itdz0xh8f5D!w3HVyV8Rt9miPsg{12FNmBK84d zrTUSKM@IF5%WJy&wKn;}>WQ>2aeD%JWePVz3R@Ll&M*-2#4GenF=`^YYF)0|fhZS@ zCQ|Epu|8Y4uAC)-pbYL7R_eYd!x^`Vo59Bb00WZ&o*QWp-vAR<{oB1jjVEMD-5>w~ zE5lP~o8Tv@>5sn4IY?_2J>22*eSPp&<;V9~4a?uHYc{tEtd^`~zT3Hy5@^G%5{W48 zaMMv}mle8x^-400A5;K1sr7!3K=EbOGI<}f_aLyX`sYh#mzIkSE)*oFM&Ym8+jq6f z_=hL=b>lGyd15Y9O5VTp+W+2g&31*wAEj|9mjt6_e5wGyAf(<Z+u{}N|C=uW)4Y~L6FmZsnTa|UNwichSUw`J zL2kLeIpz)DHiwhmPtx4=P!E|QC|NmVEEer1Le@_5@ODBHQ0Y=}ZvNdA3$S`_t>Wm=d?GB*ugL=+q&W=ghNDbH2F8C8&?17T2@`hE!Hx0Yx#M-G z?-^MrSS(;uUTS&#&JB%q&mgV*>?^vAeA{4q=!h=GuK^8T5^goC%wl&?)fYueU}kz& z2c1NO-GEm3gKr)S&UwV^ICBA*vL=8Sh?G3%5!H;G2bNjq7bH zG?*eF%oI%wsUq?z-bUN@IZkA3((80Cpxx63PPHWT2h}#cFG+pa6B9|5EnGxxj{WaI z!3Nl*@M{_*T$H$bz@B+?iH9%Ea*iL~5&r7==CFd`^v6!(UjqpYr-VFl(esR(>NX<|3Q8_77Z^Mml!Q+ zJAoWr=D*TIgf@B;dSeG4(n|1YFFPh}wjux;bS2B7MkyM5mlyf8bjUC^7)Ot3 zy(~=Y|D(OI@xVdWz#k*x6JoO;7@|lgETfj7$5UA*vdbQm?Mg*68#zjS5d|-T+CG$Y zTC5m?5audc@yipHvhq0qX+W00&Ki(l`H1|PpQzDH0Yzmnk-H3FU^M0w%J+d)l`Y`< zfFtdD3V43L)+(WEOWEsZt4sKEl{!pGavRZhTDVG3^L)eJO-)v-T?6QRuVbD$2}6#_ zYmlx(I^+tX9bG4GW-8;ka%=9Yn1>0aqmD*qt)Koy*_E882!4*iV#EUCUJ;;=7U@kE zKh?nbY{>$r{AoF(AHV?e!VzS@0rn zC3=e@Ur09<27>w5CAB~;>V#DY&8Q%iKK{JOOMMe$l$rA>evNurB)Bz>-4=F{f!Y%_ zs^q%=xnLIbig}iMY-mz1An$a?#IjO?x(aV-kXY$J-j^koTbdZf*8haf4dK#6Vq;nf zkaXvFrk-+WYs4S*0B5g4*eG{?oRB~3yCoGHXApLHdlLA1hPjwxo__2?eFwe#dKWD> z&%d~P$8qqnhO@FG&k1 za}nG>q^pE$kRN;pu643;#8lIwQCF77L&D5gS~DXRGN`xNa<^=L=*tr9JA8@3T5udd zyuORXERoHBZE0C1%oMk1VzXm49@;SK^hKHX`WKW6uS;vf5Ev)qntnSJc6%NIAfqGK-BC zvBwRk2XnQPY@SJQodB^xm);!A)}RBGZrcP%;UPHo{Px8Pd4+<)gX$%w^D{9c^}G&*!qomt2wK-*^WB$IC2_$^aI{B$#SKGu6F`p?}MXqu=Ut z`)z{-eT%JFOg>dBvCu^d3ftG&6g$Wb>}^G-*K}ZwN&khel?q)?_%va<{eOG}`;{?c z2yK2WmBXfkrHRdYoB;FB27HZmr=-~FEpc;_(leyw+3M2t0MzA2D(x-fBKeP4rPdSN zxnCnD-&9cZPdYuYovU`)h4>L+6fv}=J{1K4|IC{BpaVRkKIclSi($Nf*w z3c)PvJKI=ypOX;{auX09^XNllJ$G6K?s^UHq@bOaTzkk$WD!j4eN00jV8EXd{xKzqjOsv8~z)yqnnwoyd#InZV$tWIdu|V}Bd+c;u(* z6HPi}my1+{UIv<&0O!^>=t&5R_XxS9N`Xg!l+tbw3K$cM>v3BMgoCTl#*^!Y*rTbXp8yIdws$bqTqh`}U8US@t89T?+B>@(IYj5NbqgGRFDUFF_KH2X)Ts`DcUhreAyB zG40G9%hc^A{J;KRrV;tIPQ%8a(|N4;TIm12x+vJJp&v@;&4UH$1$V zITw~PPwAWGOBH#eaY9(Uv{P7C(@l0_byCT$1?TuJ7uVk0B3rHHK}kVh$R?6oU;fjA z?#Th^vbfj3wOjRYqh9IpJ;Y+bysf8Cvi1e|+(`0$R%WB%c8Vu^)fYyCb}O;`XGL1*OW{1Pt~DJ?}f?-ST$%OXBOR%;>g>H<1gK&k&3=HZtU>3 z$WNo2uEAS96RuETcTYE+(j>?!nKK9uqSJ50xMjV5!}+FW2Vgb7tA!)Zv|-m87GIH& zr}I*#&-;-x`$Ifr1~ELywhRkNw>zDkzwmz%K$P3d?HW;`>l#+xz38` z0Hf6x7D?m)k$>!+gDZ10gMUhv6cS!Z{xJXC?L3pJ42Igw9M^ciruvI%S_39QH(`Eg zZb4C3qOHgCbiMnUqkM#89=CU)$&&z#vmP#QO8hinm+PeQuw-Z{gD5m^ymyG1rj4)? zf`D+cp_k4&*ATu zU1(T?g7XVZaOee2?<3`fZbs})S~Ny-viwBc-`j6xU%zw(1WFV&vNhu{iKxUWzzyIL zWfyF6PaEH-=FUW+=AGg{bQ6^twV!%T6!s#HudaX`stz&Ot}~FT$1>3kYrI#m*-4_H z86xS){OJ)C`$hCePwQNBbR{}UiCW)Wiyp4k@1h`#u#mOfuhz8Hs z)(*&;+SpjaTbtm4>}o3v!-Ux;ZMB`Yk6kN+T?4?8Jb`Me8tf0=>65MVGg+=Gw}EFY zLhaY58II*u_2Ar_FCFJg!1x7Tz0zH!Q`zRD0%GJvNNo;Oq7pN#@?Bg{ll^;dl9cc4 z_!4B88W~I)FAhNa5!8X(Urh|n#j>vb6&IRgSizv@Ils*VD%k%Pmd@i|wc}1W+BUjZ zBWP1}8(_^qQ7Ai19|vWf$m)e6Y3;QAra6k#>)W8X?g6%@@Jv9L_CDQ^s~zXfAgc=h z8nksRkzn!o>*;R`1k;WL+a%U{z`U!pLUNwG+x~Yf>!*#_g)fMjG-D0k2GvN&oRUo- zto^)^UW@S=8^mYE$N)JNWfS^$&5gICJOdG;ZJjk{)GRt6M<0;dO{wGVH(dR&R?U2I zEljueKznX#r9|~w8vH}9im@N?0RdB4%SDk2XnKCAvRP%ot$J*wjlW;FB#eX?9-BSf zaZxZBd~n<)?OwKHr}GJmiWp}65Sc`l7k0TYGj`fjm_<33NBlNzI<@a{DckL$idx#vTV0RgrMb4VyW>guZoaqr?nI_eKAnS=fj$ZI5rz zVd7+GLW!&18I5fHkw#7$300V6@4(ZpXR>j6IDOIGUH$#b=r$N0{KQ)uKFdqDip_a} z#t6XtwRMRUSM+ye8YX6LLw_HRa7{Y zY$-c7r4P}Ani8tt4aAUG0l0?ACji#{>~}_ct0n&MQtknm%sGzlgm=0+nV%SvxZHu_ zKx%EA2hcccrnWR0#eI<1}?Yj({M!Yw3y-a|}m4LPHPI}rLJ#`1n#J(VV`w*h`x z<8C9)jKBb~`UmfLG$*z4{RK-h4v>t7NGE}(hht*xb<$CLT#1T6t+>6kyB>L#hhEU! zi`kbQ3_8%7#-Lk)kE_CbTbv0c(>H!)2DW$Y83wl}@NdJ?2=V3p{)vH+j>;D#QFV(b z>aC+ezAl?N&-}$})#*L!NCqk_NGr#@G7Y z>OG0gB1%v0x)OPR^WBfvrJhVCKd{Ff%U%(c!u(8B*m+vXcR%Ns-t8qsZ0xn4|&hJu?rkEh1bgyHFEMzOYlEEk0 zeX1RnNS2Sk+>Any<8tx0x!$~N_<6Kd<*2~Oq_(m$VTe>vLB*+|+mvi#2ln>d{ z33H~XqOY1VBL#Z`n<8dL+9xX_sA|f>RVwxL2WRl$jbp3}!{az&0s;5NsMV7G^P3iL$_)Sl)gu+NLN)FgOidr6|{{|(7s8u^YIq+l=y2vu6hcZM4 z;K;xdeerh49*tIV#t0>fF{uyE!vv0@S21C+h(upJFp3vi@->p(qTytuBg^)yYu<35 z^j3hz#+3V45c3(biR)+X_gtS(vC$^eKAseX=%DR zm~jIy_w2m$#+>p_=Sroq`%}S5gD_vPtCI0&Hm(Uk`lbnp;7W@m?bQ%kbi*Y5nCi}h zkSz4zlMx{OzOeaYeU+kAgawA?GDCp^>qkTn0}`dK&1trYK{LrW^3Pn@VsA5f$OMjNOj zT~fYS=fZXCe;0sAS^IXCfO*;^xE?zG9U3d^udMxo;sh=trlMkp*L1$+%@?v`8 z(5C^(uOi~$e&6^UNv5_H_5WItYOgQNhkT7 zr)johTDI=vw)b~MRcg@2tP6u6Ch`>c-|^rdRcYUy7!E#2_&l`{I@;@@^*#O$aB>!d zo|&&3hmKC(dSS+70FWwt$i%hD>^ushJSh9tSWaGJjhI_gw^0YEk#ym6N$Zt0GHRJ* zy#p)OH$8@r>;J@lWg)VK2yS9CTZ8I_A8+>`crl=aZ>uTPy=m?U>Fbyh@nV9!il`u| z?}82G-26J9zQ<*W)mHBICGBnm(331Pn}9z7^&#&b!>nd2X@Bfgd-04HDX*pC)N#`G zkum-dUF!9^>1u_Ytb3{T6Qle*$A920^rXc(5dCirz%N&~nX>{1sQndqd;#}WNQJIo zx|%zYYgq-6qT=Si_Az9teW0a6JOGz=7axs&0}i)^p=n%ZYzr{ml(=8`J&Qr2hhB)& zJo0|xdXPvsnORmUDZ-Ooo!b}5*|k{Wd`>x1tnoD3mKi6d?NUH#zbBmGY_y!{h9A}H z9IALCk3XGF;tS$!)o8l`2>3u^uOOQlgq0quTVhYMJg9k&wx)7r<+ZJqlvAAd;d*%; zriwHxTl}9FpRGLzi>^nhxvV}~k0jwY%_gJnj-?-REt+t4BINPBZ`+i*Gno*;`{k4^ zf*sm?QTzyWdI_xC%(ly=K}Tnrv=eJIgM6!m7D2$7?gX(VD07bl?6yIg^QQ^W?u-w( z$$a)=U&-b!?fF~9Njz0#?9zAX7zo$T$JN6* zJS!+|54$LGWEG)4&`Q*QDm|)kpf&ofQ2Ln>XffwwIvQsARVZtZE`B7C`c^Bo9pm=Z z9?jBmPWKZBO6bNvW$yIu&l)eR?p|ROH39cHd?~_DJ-cCcK7lPbv0zFF62X_n*4Gjc zL_{y5zf|fAo~yUvPXovoo@f1{b2lsdD>ddEVf9RP`my`ge`V0b479mj599`W>H~6` z&lyXb?zW+s|mQU$-(m$x+u%{}8bUMZzmY#nLGZK{5Ki)R!fYN{G_{34#l;nSpX5fQ*qiOOB; z@_pG=6vhY5c(ZA;Sx4mVeeuiq?}m0I+0?sMRV$tgqN8vE7&;MP?5#_`l%|k{lRBUF zl939YK0b6?Wc2Yb;0|o+&zT{q2#!K_whsRo{jwfiSo2vcz?l+LYS#VFZ+VgqQ2wM-YT9Cw|bZPfB;ll zUg8(>Jj!fNkH>Z$Gk|xcET6KkV=>#7D%~?NU8<{7=y)bEZxtDddgVNJG|7XhKJ%8z zge4lH6G1N(0*K5^iZuBZ#{8pL>V7;y>3rDv&0Wk}9x&}pi!>QWFkz<`Ug)eSC*^v& z+5pnop75&mp%)lSy3;a;T2Vz0BMa zMob9Z5I|%*^3G>Tj7!5eP)Cs;9I{u?lyVjg?oRi}I~CcAs`~P)0$>CtJQszkO#|gL zHMN<3R;fKW|FpqHqGy;D7TL6NiXnFG^~VS>w|kf?HTe2b&fWyyuZQ7bYr0M5V49`% zJ)Yevj~@mk`W-Kx5lnzS-BGDm{06~>A7$Ye`6f6r65+np|Fq4OB9M}}DEbbd_?gzB zG5WHxxqk=X^dF0h)`Y5*8!_A|gc(@6N%cP*s^wE~1VNY1HTx8l{(keEPydXh%TkF( zr6rg($vRiuo?_Gavs4tc{(w8ipQ2{XOVyWv#ZRx7wz^aT_&p;CSr*xd5dk?j<;HaEn8q}VzT z!n_g#EKky|4&Y3@I7=oy@tT1~ZN2f~`hskUn|wS@wOE5Ue<~c2{f-8VF;*Z}aj&-N zzj>#$spXo|1VMHb%o)r|w!rK+P+x{YW!P>e?8-+VueHu&eI8|EqI~!DXv{O(T!~_2 z!m5d=&%5QeE-TEM^VL1-)Ra-#xiU$~reb*$JxCK}g&ne*#^oEjzPE!0L51iUKthSZ z-tiht>iFA3i1PAZ+fTk(8<=AAif+0%Z;j|Fq)gzk6kK5AZR{DhNN`Amd8@jbN4o$U zpd^8VdwrBkA@d2CT&p5-Eu%qCsj~EzQ1ozWlhPI8>T?bzX^?9g#bmcV_Pc6n*o2TW z@!0Ac+dz_~2>`|UgFmCJ3k6GTR>TEN0vea^?Fg&VUs(O4YRmzL(=EBhp>3EeTPpWV zH$$!Z#j#AC%0reBUFEui_MxD!<;o>5N!QvF+*l+CGIq6+O$Okdm4Wia1wCdsXYC0| zxDLrw&^$!fWd%nzr)^C04Ph9TVqHnjU&MA@a=Y!?oJ42hc1W1PlAH}SPxzV-)uWVh zxps%+g5s^Qnww$SRm1Fp7lK0MOak+$3Z+J^Icj-A|M*NiNq$XsG*VU+*1uec#Yj$W z2IK-yd3n?Kw@a-tihIC4ojUeG3#W4r#xQWoNd^;4`*8PH6Hf%CHmGmMM3TF3)UnZ; zJ(R`t#>%8ZO|AzNs6OH$N$OFDc}+j0(Re&XvqRcFg&H!y_b_!+)vtKiImU)K`pTc- zCi}!#P$Qr1s>0tU^+H6p(OFrkdt!mCe_*~|xk(lGMFGYBdkvy-%@XqiA*MjwZ{k15 zybLc<7G<$b-VDzKn=#Z+0d1F0pZ5gBZPv-_mh$(RI}d&&hx&?@7?5-evlpn5Q1LR=gC9m3w{mQXhLSZ zG+DdVdvXoDD@Kbp{d1Yh{v&3B$cZvXj%W@`%I}8=LT_s)sn30a9Rsw`Z6~Oa%M{Np zTyHLLb=wxa_0eidhYD48z z@<<&Turied{{bO>+eT+UL)Y9TkoEa%=rjmIVdYeBsqk}>(p5>i-M>;|&pNKIAD&SB zcx949=bNHjj&TLHc?(EBWYgI_gT=hq!WCw9`T|N zxxj1Ijq?kk`8;-u2jx%_&9z(#S6G`m!*ibgyG&9}1^Xr1u8L;E2w1yUKxsqb-#&Hf z_1RrNd}|EwQpdkLByh*0Bd6v0YqvV)7O?nZ8V40)Sm^R|%3|`4vH;7nBp}yMM}8zBPxO<47s&naGkVTo$*bJpw&J|9cjBXzL;Nx6Q!X zjSbYgKaRNbbo`sNTt)iAW1C91Jr7Rj-5j<`Ehi=@i|hJKuI!t=`y$MFAR-(l_J~>@ zicMs)h#dt+PyTVn_$T3?T(t_>c!*V-7rN6>@4;@m02PIb75?Ycirqj%p||=tz=PX4 z4`O}0_!Qd*xeeJniL%0FbLkLnD|Oq~9ujsiR%K;>n%%P`mgt|DdkO`d+~;)Sul}xV ztNB0re2dVlgc&Tr8S08Su!MLwm(RzSjl#$HoHgbC$g%7P4~eJRFGDX=zdF7=l}7``9# zZ^m1k{S#e~rB|9O%GWR$RH7Rh?PyYLHMLGyF$x&PlVDCLT*N+7bv+U?vD;@IxikZP zDPvfra-d=$u1tk1#T>}^m+|ffOjJ?|K#FLE&3}vaJ+lZ#kRxLH66)rDR2-j(0cS5r zfGRcUU$$W;FZOSsq>YwJe^!&*-KYCV&YOs^3J(~LKYL0G`3*q0aVL&Vo1KE2@0CRc z!>eaqe0&tQbEZO{9Jm!AoDUF-qsuBh6Px$sSJKxe7i>l?C7<67kv;W)ORkUnUJ+fg zJ^(Y}3tGL;elu!duBc}4P@&dmT5NuvLfmX;PC!Og6^nJ$Of>{sN%E%z4VrakE>MV- z8};N-|Iz{u$HMmY`07Faw%CB`W@EAA0#UNM{Z$BxFJ2E=Ndt0Kg71HXegBPTNX(e- zr=!HrEy0tcvY&~RLmeG6F~h-89=_^A3GhWkb)bh2NN?AhCw-A}bv03@8j_1OosnKI z#y_5{&GpPt&~ErT21*s93JKdlW%|~$!7S)zk~lH8wjcXLYR2g;X^E*z1fYKmaqzNE z+```tn#q@nx0I}sfa!{;YBDE7kDa?^mV+6U3P-Ea14{a(eLzSbN|mZX+{(+Sy_=Rd zCV%A}W}u`_=52hE#am1lxPr-bQ?!~^?SzNZsd;+r_NOVJ}_^wMDAsF9Kx`z1TXPdRm9dhQ> zpZoKL9_O3&oED)XtY|S6HH@2HjgCpW+CAJTQ6%IQl+MuW^HEd&git)43S1*6I~?s3 zBNe=>KJ_&1TH^t8{7h&@Fsi;$`II|LDsq}BtIJRtN{@!W>u@B&763Q`?FiGFiWB4j zX7Vjvkehao5L6B#l-I6+xvSyOB5*C2{(P^$WJxfOHee-`Q@XQ@Jy!9|mkFLLYX2{C zQNQ)hQ<)SwqK|+ag?X6;=S74y{KyD7k-kW!UL@Y3r{3fdt{)ezV?r*4Rapz#mt=j< zCGM>%ogxNtlq!g+jLS7axSTxUTtu#`D}&fbMI?`8jC;9RZKQ$7tRc)0CHFo?$XE+v zF>TktMZOD?XZz!>6FBGK?_SGK&CM3@`|ns8ngcB<__1_dmA&zKeDM7UIao(oF@z^hHWmj<-mj6`9H$n1o<7eK zc=nYq;C^wzb3;T%p4C7Db|OJFM*)0*+hbc@RURL!cgI6ND`|sl)YC;UXqG1LTc2rP z@!DQFi*fRdVTFG9bP@)3Zl{{3sv{?4-g({>6SSN>{~@}xh`JH0r4f-xL8l+wjGnps z2s2G=Jf)LmoV||da2EoEMumZD7?x^}=a6=kET*<3@UHypP9w<0gxDcyV1BEd#N3Vt zDxCh<$d(6F)z=-x$=8}qAZ0@HRPd_>#Ae-NOQ)uKM(eIVGV|1MJR9rpVO-MF2wKwp zqZi~ZmOHGW-^|`LxyA z4e@WIU?`%muiX&gS%FKYd}X`xHQt&D;U$k-jTeVMN8r|j+$j+;Dg_#nbPsC=X1Lsa+>;N_tM4ak}0)^E!!!IO>urWH&vizsbSJUgW zOuzU#A8l-^cwb@sqPv!{>u0wo{$>BL;g39-Q;X-Q6xZQ#H!T=(aHzX=GH{E)X|&lo8+TROb6VpGG~04&l1>h^Qck8ve}h44`*oc^!} zI_05z@DG>mXP{K#lyzUm%iHW{7XuNT;RhDF$_VOOb^@1D*sfsd4}?_F{hn2?l>vq# zTHSmMl&#KpSW_q(#RxC8nvQYZI$QD=X7SL6$xB9_HXL?)C_5Ji)kygOTIThAXn_KN zv{G%%-8RSNmvI3E`Lb~cMv#C`(9{Q`KVNeK*FXMCAf93n9tn$#nV`1CIvhV=u9AXs z-jBH9Lt-9wI@e5K}V- zhF9nA5<#c74>q7gd0O1H{5h4e-;a~pt5GX9F1r^LyKk1uRl`vA^vAiG#}6Uxu3OVB zxv$HBK%OyHLOfjWAhYv>5i8Y{9PqrKKOa;act&i)O2DcqA<8g~)-I!2My>pYec03H z^F$n_Ra@~!fv5>If(9($+*3omVJdUP_+tBI9>RF*0AwFG2pEe7g0N*D-|m3PZdM3Y zm#31A-+H^3sF8Lxd9dZQQX<)4Ut55)_N6zNefW43xz?iY;&pY0-0HvZ)m^V>#wFK& zVG!_=g>!OpLWdm%dG&W>DCMS{CAT~}ywprBl5ThmIqcZeUfInrYWKU$Z>#14jB%l! zdP@4sw%U4+{a_8f2%4(e6^0-@auO7gk>1SI8w){x`}9=Gkx2#RwNc`3nZ{}F*u5kR zE+>Os)HDPP&8!*ErFTocSiU3Pnz^c>yJG8O1ESGIr2fA`e+iUrr1c+DjdO}1q4gO) z@1lYpBYESTAF-M;Fq0v1nIpW>9m~nXic+=otKw+IhPnGU?LsxPNUurhNKZ};Bi1L? zy~s#`NLTraHcq4{#eOx&2gbf5a6HH>67cJ?$o3|sqVKpZhvjGc-BI|(s3mF!UXD~x z6uwPZ9?NV?1D7{BArYhgNl!mABa8*SynR|;}bZ8 zZ-__EU09&*#ZvRnepwos z>`s(~s7!6LwQXy@XutzLA+$zURIEqdPNJ@=1Q+5xQ&2x6uSN~Vv#WZjn!mh;=jxE% z@jv_*T^7cL#Vd}r?&6d##bFru460iUIKn%L7bEv z*V-O_lyZyP10Zw|1Sv_KVF=r-Aqy%>(;V}kE}-_ssGb3Vx72edu$E@O=3Q4209FUF zi9S>s4Hm*mtq@?{#o(L;Uii}cU}fTY9Ump{LN~3!9PUJ4Rg8Z+C9M>Z*fDgok~(k< zqEZa2$z~5b64uJx*!=gL7|JQ`Tc6bq?g9EbQq*dKE&`0017gs*H0d-2m1ld{AEeF# z{ZP8b(NrVi99a|ROr~r6PHkyYiOzgyIZ6ykjC{Zi$m4CM^j(`CgwT%;KN^_5-};Wj zt!NYyTCG?&;#w_Q930pv>P^qV>xIf`jduxqqvpcO>40NL4w2|MDi9$4b={2L24_V( z;EX-;*MbW!`2r0)Dg2S@f+rRZRbymHQr~Qn<9hC!dE>+@Rrjrsi|}{KUFU|k=v6?5 z9!WnCGh`T{JV|uu6@PB^_SgHFD6dfTky@uy&EvTspinO0Vg&MgT?TYr+O?rtjJ7^= zXp2B=eK7_jWZlaHVz*{z$O$@=*(AYHlOUdD*m3newy6gnQf#n+4j@1DhWz`AoR!BI zu`2wm40$i=xl4IJX}kC;Q=R%)LDX*SkKmA(O^pKI$tEXLOwiRHxw7EELi{9U!_%2S zSZj>6fvuaeu3y%<211@Q&fb7Pz^v=Ip40&`b#rqTVcY#-J~(kzelnBIApn0JZYqi>|=XHj5)!8eYkW~y9vNtoDb*e}1;4+`jrXkISJGo5QU{Mk2z#QV&l z5$O9wF;u38J*THm5E)ZTsN;h>L3Xw9w;~pymic26f0Infmyl(>Ic~M;rTl|Cw^TemP_D#9N+^1en)lLwTe^lExnu2>R+vYXV z`k2Q;QMo4iE1G{1Vic1}q>Z^XH=AvpJ?*AV4~J#C7+odu!M=oF0OAx8TC`7(-ue

h!+;cV{-F&{&1LE$h*91=;-Zs}q#Bj-Lc~xE!BV7QH1%oaCK5 z`RW4!hWpKxs0sC!+Cs>5buqdAV0~|p=>`=>9bu$>+EV1xa*Tiht_7bh_wMlOGCqDTzYAP5#td!=Fi_j0%EVIJD^+O|}1IPXf zO}iZK`c~#o8y@2ZRPKe6F}N-&9v8cHb@(b>xGtUaeL`)uex<(FHZEOZSxmj39%=zJ6QLM z3TD4O6RLrH@(kcX%}WD=d0v~-{`g#KCLBfjIeW5-nyR9$XlV6+ePXjgopaFKf*LxM zQ+ew(QNY9KXC5b#v9}Y(Uyrdaoeil`es>h$Q)pSc%wGR;Sj>K^H1wyDi&?b%YjL=CQf)1B|_xjn|cQJ__R7y#3h*jR?KRdNuNU6x;+^8TUqfH zu)b*tl6_QnG<%e1kdCEeN%Umr;>6vbg{8Q)nm48y5A}x;xwzVWX$2ChD$E zyGpB-FF>O&$q^?=4}wjjk_7;+ARX`EZtdp;7)s@+c|SWDrat6b!3erZ)p1LqYOyk< z$SKo=h4vBM1-{bA4Gdi1{&nwVni>5#;*}eFIG?xqe1I?R<5gW-dmmYW=!O>~&1L|s z#Fyfh?N#g-lKaFti=3xm)qLn-A2Q6Oh)#%Ak$T2puuJTPrTEMZja^)iipg&Boo5pd zm1}UjBeacifnq*HW1EhfV*-aJl=KwbsrAn{kkZ;`=uoB)c;cG*Xsi%rj`?KEaH$)F zB#9!%J5AfgKXg@BqPt4P1(kFW6ium->9dyThFeqH3say-H>7TJ;{7w}JLikdT%uH? zg+lb&s9Osnel!3pshXL{>^s~gVS8lACkXtTBz$k=b{XwFrx^qtINU|96=wx$}- zX{?+aqowZX%u#0I>+lwGIjQCz`zqO1p2tVgHLysD)yC^-0}h3JIAxMz%;P5EoCUak z8&%$V(yt}up+mK|1Y=5grRF-wP34IXDruEu=&hXMYHDoK+zH6bg#~4^vnpMhK_0Uc zlAByKs{pg9K062*n98qGK~fiCp^aGLtcM)XQ_dV@)J-+zkA=A^IRaS%J*tGvjgD6` zfB^oc!=9gux9~ei1eyz#+DTXEsra5b?_Wr8D#!YUaEjr3u*F9BFhHw*c-Ghsd=nHu z$X=cwCvGtQbpK$f;=oLJe=G_UFqgxs*3CoiE0)S-v~nu)RSE>IA(g6O*2~9q7x`V*`p3>eVw7wRo?}v{s}##vrkh0 zTlwvc=*Wu6Mo$K%I&E%6r4O9tz~b{ijq|iM_3O9kldt}8Uo`vMWz+3p&tEy>M-h~P#Z~jm5 zET7uA-?L_-NCrJvSP*|LK;;}kPVX~9`HZurc;@jk^%<{R}>m#lfPx^jYQ+yl5*3o5q)82 z(r$05etwKo6kQ8&V5yk^(A_y`4Y_iFWGkh>NVh5=g zz{nMU_5R+;ABSb|y(?{(d=ERy^M*AQx@MOVJ{e+McNP>Mnv<13CGQp6h?H_ z<&OQygVGg`PP^$zHxJ^ls>M-MudkrF`|p7V>0$<)jV`f!w({_A>WR%2IpreE-@aUy zwB>@DA8Cb|XNe;+V0{Xb5Xfth6j0SD`RG$^0Qoz}f2~e`5@1e&J0Y}-$Kf;!Zxf!c zu$|Qf1|G!=xZTbM-B{+tw&Ad1r()GUwbq%Gd3-S-0s$3k40yrXW>Mn(4VHA1IWK2w zYa9Ro0@FdBAY_z8Ts!{&1<&aiH-h`S)7u!`h_6o*PX`7v ztH3_44yNo)CXc{CP~7}J|3^MTKN>!8MP6~Jvy;};7^m%>ajyAzN~+kh)#X~)UkqQi zc)H55(1sF&DWk`qj_8x~9zJdU1!y$CzsmCbhbjaYbw|SB3ut8(!hg+W2sfTcGHaA=(9g0}jHS4AiJ7H5%tI&7w*eFdF6%QM88&c+kjS?u! zb!^!1tKGW2M}I*rDy?b)4mXKyRwg}zumZ6P_$*`jf6?&p$fb(7Vo|(%>gWCA&Qe&g zIrCkRF@#`if%*=NPq=2xWT#KqsyNR>oicgsZh5KQb;sgM({{wl|R@t zFI3l(JdBKc2tQn-q+tkjY~;#ypvRs?IX606T;XYKEGWhx4X)m*1ZYyIkNKP2SCb;K zhXtax{D0BGg`KA#dQq{@XsfV{?2279SRKG*0Vq`sE{Z%3YsrPIzI)E!NAG7Grx;>1 z{4h|Vta{=$vh7VpYGR)X!P{oolnh?tVJAbts6`k8(9Jfs>GbC1>Cz-2M2>#b07pqc z7xz8fA7+?buEr$zL?!E#tONqeUWy{z$r9=1`9BIF2%`xn+BK-5t|?POo;>dW>U`>r zf&mt1qm$E^c*yDvW*APjKwJlO%r;;s)eg;pC}|GbeelyJCV)4PQyQ@W^u#9u-c9$% zT)3jHnXMMt)_(PJ-`Oxk6Uca&%`{BR5-XQ@zLQMN6bO<#z4N2nPM93b2I>xNQQOJF z4*&oHB>|paX%OE40(;nWws0Fj@Om7L?qbQ^imYZ=?Vp*c;$ZpZleo zxs8EU^S0Uel9r*+fNUp#3r?akQ%)13yLy=M*6XSk?y3|738GnGBS!5awv7mCAKnYB|Dq+(=U0*SFr zkj$U(e8x2F#(d#b;|Fp^IneKO(c)1_ZhH>>r-!Lqfx8&@TDFhMxhgZuL?Gngj?AIr zLvM3LU1w}RpMI2+op%Yu>KZ8lC*(nBjo=z+ELAgyCf!6LCce%YHIB(VPr<>(3#aSh zT5PRSu1t~2Dvpu$TJ*S{{0Dfn;+fHkbmuCc(bDx5ns-_WM*mY^@TH_Z@qXA@aXUHB z?}1FAk%8txj&r|-JaujBTIX`N^`f!(nlt}5nSn>>#r12z(;zd3X< z6pFX%z8CwfF6*ii8Uix@tqpQVC5r0ke#Vi@01d~?LBIe20|Wt{L2g5T01FVl2EW(< z1=IX{ECe++*o#NsFOxR_q zh)|ILHu*^^E{1NAZI1ABs5bP>L`EQi$sgapf0X&$;Tot=k>zz<6J=iX*YLB$a-Vc8 zs85m3JLY5i5&F*ohB`+kdjG#ia`}FUAKOKT!T^%Z1R6s$U@ZudtyphODDD3fNwQ|P zOeHZ}(Q|WxAY43RN2qWZMXrB47CnT~;7Cn`koXml0{J23npO-%V77gl+D8OiJRQEg zT)HJ|jB&MOQI=)}6bL-&IV4=^H@iYne?O(REVr|76z<)aOmKcyk|LFnu}`3I@2#Wz zkGF?^8$bWcf4O7r19F=+t1i>Xa8`A{4wnWZyz(Qge&{qIS}=oe=XK&w0V@$_AJ;0^ zk_)82zm9~VP|;er{TntNvW8?{(XtucY5BebcxpqPYD5}oD*%SUqT9|whg;rvewveR zqi`<|4@54`?$}~dEkw|Td;q+x$-T=WC1@7eyz6xg3^KMSQQrJ7;#ew$E0P%dyKK^0 zdYU2F1jRTXe6l zBYf=Z%si+H{u?b3Q!4aXZNi)}*-y$-$>KfbUJkUhonn%tNA&NL)kG_Thj$rYYlnD9 zKu0OFiULdw)q zF1ebMea446Cf5TK3hkFyX4ap={j(n|4vev#W&2`ey}kTYgGN~w?GwX^X9Tm(C8%)W zk-rq31ifZ$^V@<34fSnhZbMQfhX-v6M(f&g;Oh7vaibe5t1%P6l_Pk0aoT%yd3nAT z-$cwqFQFB+K_wc@ltgt4AyFUU{6LA0lAX`D2L^TL4sWO-fcq9M*){L+O z0m-NUeJI_rTyCw?Gq?!u0`aEuwLzT5Wn@W+wsR5KC5M9E`fO}3-yM=!6{d)utd%AO zVK{Su1y+BVYRnA9*`ziDQe3HUL4>K2P&uF@oip8rnni0lzXdu1ldFb$M&h$y`cp)J zNdkzO)ZMig>?hf(usD-!^kfg*bM&(lGvw2GwUtB zB#DICf^|mgJ_=}08RRGj<=nRX8cmD_2sS8vgueicX>*O?%jXI*c-~3~dv;RMr!A4r zl9~oYBE1>;OVXWWEcYf@l}Xw^F)a*{!=K=z<%hldPRP==89G3$AI%>dg0KagAbjhk4I0mg|Cy*?k-p-UB|4Se9#L^kaN7TTw|8sSIJesta*cQ zPlXcAkaW{&TBht#%n^YF{}?|uQ6zZkwkzfgqo0O2Nt+Ai_;3RSYdmJXx(e*L^Z>?2 z2yngP%;ofo>NB!#+L7fZk+K=%(X2R}sEE}cHRW)I=9CWHktqn$*T7N8bW^>#;C*sp zdz`D~p)blnMU&QhUy{>!`}yYl&d*0m!vyx|CXZpLOIwe=ZfJfI3anPAlg=>RK=B&F4p`azG48*j=C$B=!!Q^Loi7-iQOb;I-_-2px$TEc2~&T>6w~YY&>r5gOeO6M}jz+zvq3N(wTB(PJ!@U(G2sCsNmLCbS9TASP~LK2V$on{7E$`<{G^ zkXlD@X;0FQZ5sZzcE2tGY^DF!SMbtUF{uE}nic!!0qhHv%WcUUH1Dy?DcXvctlo)1^xEc&Y@CH- z-6b=B#5uZM_K*gT3c~wqHksMwpd2tTaD2@pFrviYdK8=EkT5{qrAy)6)7;NMOG14( z!pF48=;Nor0ZBJ;zM^^05JwDl=-6qDbrOo8BxL31QoVwqO&s+$!jhke1d4;krCc0K#@uvcv5RU@6mm&UN|ePES`i zFL?JL#8!OKHvlw_!UuJBUXH=fKmd6Tj8Pdv+a46vtq&q&O?lx#q1@3+LVMC~RGD25 z23Ip%k-envjSEA?pb}ZvR1vMH0-*A|$A(Me9_naxHY#z%w(~t|-1We%&}*E5eW=Se z0Md_ABd;!p2nIB>wda;LoBm(vY~K{2%!Dn#?O}G9$NVkD>CRI0+hv)jtOLt>_2ZUN zKr?BP^~VH%>PR4xuc0G!SEM?J=2hn1Av~$MXt`=${8ZJU3pLyuJT-rRH#f@!R9tQt zMLsUjbMSKS1H=%I9@Bw_hu}LjsaNn?VgeEfYF4);}gr>RNx}&v4p& z?N1UkzCGFv*vla!=Da_mY-&XR_(*6#GGb5$u4GRjWklWXF1Rod0T;oEEiq=wX6nHC z8aM~X7>1p0!pa|Y>I^p18g_Ik#6%VZ20;@4ocYkcQQd;?M81`a4^BNA%m-%i+Q@|I zuyADJ=S97b^cZ^tLIcN^jRN|>yKc}^LI%xR$@DG{UU3e2rCG)!c%?gI8SE&Zc}7HA zYHG7`;O2O$c>+E1eWV!a&)921wO6Ld8Q|s7fG8)mhZ1}`olWu%TR4kT`s%svXs3HQ zl;`5z8$=wuFGS4@fZ9xxQG8Q8(hc%Km9~PxvFAX;w z77-vq6oW!4=9_Tlck1`+Mc zNGgnWG21{k7%#U9z7{E`CYl2r{8OGy$^HOT+h@l0-y=z`_48!L(GsrZ(v!@nC)~&A za=dtxo0VvY+O_h+`>B3`b77=viZW6#96E8`m64P z6W!J@ms1wO&B|cvv++c;+0LS92j=z6yW9Eimw60Jj@J(XRhw&&IXy=2!G;~VzuP~7 zYtJ+#vitndBiyHP=>X@*wZ>o)_i;|9XjmYX79|?s6%8i$`#U_qZF9dnDU?j`8E=Bs z)lwGPi;{`QN`{*2{3Gu#)W7AfF|0JMW12K*tiF=eo{mXB9vn8U>c+@M}h_rkc?4#3&4p>gBWs`mVAR}ZEfl%Hyr<8 zKipWVYzhIh3gwadJ-Nm&QP_Ydnd}L8eAvJeCm&NggwWbnOG9!7M@CqO;?{N+)VacP ziH^4vL*m;uiO$U7&-C(56DKS1=^YiJDM#tjIgNm8)yQOkg1d*H&BZj=2x^N%3A)!R zK}TS~h?;E7jAt^^bA96&tv2_fEJSdH++xsik<~N1>?9tA?TW&$87pj6wfSCDG|`hB#;>{fB46V||-4a}r9lBQfIAC#1{yrmT+TIip%$!@xS*fEGL1%77 zuUl-907kuIVLXzo`=f7wIu!rT3wFJHBs8HBP6y~UT+DfHD4XAb)X1N9(uDIa|LaRI z0EAQ3ms=`8qFylep_I{6dK{zhv--Gs7VPH`tSQI$f>zAXEVbq&{-Fno92*vMCb%aj zOwXlMd<6(5gw;fW7;kRdJFFw!0O?pB3m`lOupD^mVP#LYXe&mu=+M8DrQvoMJ6wrO zC?U!*4{X%&0rMpuT&B>xf3kj>y?bK^$OdKDwOPRW#%PC@c;MZZda4J>nONT zNyt~bxuQn!yn3CRrk3EAjMV!EUtGR}^!L9p^C_gT*=DWWzL@`EjBB_wo^5ku9zlXk6sF% zj-IE~M#&4epUYi*!XXA@nVb#x)DA)v8TB#mb~m2rttBX5EoHoA#Dt^GkU2rY-@! zo*ooB3;a?g;Dr>)6@DJWmeB!cIAK14MbK7?&I+mmW z2DNW7a*xo+hFK&r#OSIMrnFQ(+MFi_{U|9;g!kgz)yW8bFveNz?hk0x15;|Q8&<$( zlcIiHN6fZNO@1XjWh`3}<$4r}Cr2w5`pW^xc~25$OOy@|0i9WS<0+4}w9 z?B|vHLH|)tAI4jx`u-#yiGJ7($@#MR1|Vn`)588bH!dve70-NdK()~x`Yn2`sl~W{ z-|e7=`IGhjfx%%*Aq#J?59Q&;fAXFnvL>8#>g?^*qzKI?FMx46G=*BxvTZMyDch%I z+t>fUJLnxtT0LzxG;>OBvz?unXm+td64>+K(?2~Y1y;0mjLBF{jzG^ec>-`rFD&Zt zueY(0yO3OXoGPX4UqkZ~1EL*-E6*nkQsAD=_3v1sii`Eweki)=A^ax=>#7~tV)d?>E zm_;;P0P*H){u04C#DQTiU6X~7n%s^#fB=zm-Tn;xp=-&#m_et}tXO0(_wwr8oQ1J4 zCZ$3c&-56wY#y$?rIZ#QH7g-RfOu2X1jr1BB@a;%sRS1+y-8Zi8VfNwL(Y>P<~9Ai z3g%0pA?45}$;9yimCM~J4JYJfdn^FsE`4K&|PT0KI%wqmI^Ht&N&Z*D^-&YxlsKkASf_ra_% z$-(!jcWoRH&uao%w94m%+0hg(KKTx{3HG(i(Ks4jQRTxnDN$^R_Gf>8OHEGWh(!zy*ui(f2kGd%x&&nDu`f$lQ0`M zq=!tG%WSo0HI;u{!szn!CimROm1HID>DmC32PjoWOJ8^c1+^X+ee_n+L_j9wYI;2$ zEVG7JcyTxz4f3<($N0t~0#R~;?4_mKAoNy<>BC(C)W1As*|J&$v0cobaAc5ZSYyn zmLvTCWO+`~iNVRUL7m3(YT)Gsiq)(5Vc(1x?z6oMFG4?(a+SJVL-9R;B6V%ggTXH8wFr zve^XeNd`$jz^9UE4i^8n&vw|Ec;Up$AQG$qdI?B&A%LV1vIXHY?#Td&nzx~|@mX}o za>$U(ei?-WzI<=LMr*w?Gs<*?x&fbAgPj5Vm1A3Gc!TJJvU}fjJ$&;rlo?*B6Ck31 zEnmVcFdO&J>{U_7S`8)_LuJ04du5r%D zbp6NM#My>FM2N>v#+}@!c%->dvO>Y@`=%y zBCRT#DAAsh%d2W|3bfpbs?B^R(E59SBrgSbIO|Y;UX&yvAT#V4T0M5x>Y{%eWq6;d3R`}Wp z9};(CVh^yoY5OMs6L6n@^OXjh>0{bzzA4xIpb=>cwIct*ao%!tc{fcBH*fs}XWpYr zOrF>49!Af^n+EvBsWTTj{t6G4pGa%$`|^Y&5BDq*MH^|7(4uU=Ygp5D^jYa;ad2=% zBHf7LA)hLB`p1QX-sTqexyCN|qai|RT7;YcE7=4oD)RLSryFga?}%a&i?woVF_~`l zWuLl>j{|g%wb-vP@P^TXsumTpA9l==E%!O(COXxwQlU`F*;vpLmGFxPGm!=$)?M(| zJGyLezsD9rAKHO!PVfF4{M3O-x*e081q>rUN5kZmeglY5S<0G}uIM7{b`|jV>8!y1m_41U`N@5un zEn@&5285ZYamGnaHo^y-)6`|?t!RubO@#2Q(2Bq!<518~Sn?b2AWNq72#aINn`ye% zwzLpMTCCy$h!3SwVG*`ylt41Ar0WSM*nAy7xSJ>&)$LRkQPet5*G6ycKUwU;DmNSU z*`}?&>jU8J(-(z@al~`W*xzG*trf~t+p+4a4wT(Slk^}Rgut}x-QTwEz~5jbzZ`%H zf55hp!Wx3%>=2&mL!Yob2K5v38->MgGivIu*H6Aokf&aBg(h{rGb^zIsUNrTA|~}f z{7N*SDvnCgII#9r3qj?}YUs1S<}X}2L?xHV_tuN|PiYSNPOM)dG0nJ_kZW4&2B`3* za*kcba>!KpGllM~0yZ-T5nWwMjt$P}!(xg1$X@(N;T;eRFls8fbnLsT1KwxF+h$aO z83vqQjlqC6$N;oYh4M8T6lh?vembtYGf-6y6XuQR4;>~VnG>>C8`X@^zNQ7W>I-vZ zxoD-E=<_CNH164h67+8-KR||i%i89p7>=-|u3ZbP!9xV^d=V0Zd}DExzY>*Ep)=Q6 zH4mMN0NJ#?rJ#s~Zl3vkzOq*~xS$BVC7>v`nVo=PZug5YdzjjU|pskSK= zIaAO;c+&0IFt6NS7^7HP!2wegRWVAOkw}G~(=$2IM72+qW?UED8CJDa#Cnyl@K$T; zxltUTO^~ehXSI3&u&Ai*DRRaDQEqB83sz;rQh1DIe$$8v9<0N(1iO9P+=VPfVvEG} z5Sejcl@=;J{!9=h{|c}-?o&_zWu@uH|MJL_>VA&QxDkK9UZseazV}4p-f#+U>U%=< z5ODQxM?$A<+pM%~fN-J*;|~*=f&~1#qRdskiCfxQ6NQxJ*|_E5v5Nn;$`xuI8r;=# zk}dh$7O=pudP_-AnjEnw!wVvE3A()a{QCWpvXG2R8jettL?r{BK>IE-E3v7bsY3bD zas-U`n!Yx`Io=~b^J-*ZS%1u;lrz;e#A*^HSVy593-00+Bq_GR+W_ZX9IF+24|j~O z+ztirqvziz8V38{v&`nQ#j4eikT>r5>b?-0Zt`#{6o*tLs=?E4gV{Ay(L9RFjBG7g zG|2;&(Mf&?Xs>YHmYd!>9Hma)yR9FL<%9h1jVJA)UD-Fyk89pCQ$w+m{`V85(>XSA zJ<}2jH2}Qg%z6va_|H|*SS;~o%D%>sG7^6^$XO!Z-^m?Nx+*M8>#xIo?tORZG zgoVEI-CilT&3OW21$i<6xz1D^>A~n1%zUjTDi7rv~I6BJOI^z z3%6I^nk;{r?vSK1#rf)G3nrvj6TYfTR-SfI;)S>M1oHlkPc|6nGB*g|?7r4m4wOjU zGY6_mt8yLU{@9~Z7W73V%yV6s-02WL1nx8r4S%cST@bx+vL!4cmVL;mXDOO1I~(?d zg(vhsOt3!05pCf}Q&ey16pUlWw$;vjqZR6=!^NpNEeO=VGxvu&#Mzdp6@uE*ZcnEh zrgIFeT?T7c9budx5lQr_ShwzyD6eFyL_rwIXi0-EMaWkW2K{zz19LD;uGwO3P?E;~ zw-0yR6X#pAO%#vP7iF7jk>mJD?grWW*Wb}2X<-%b_s?>_nQW$Ldy*i6jLCqE7m-~4 z#~CpjC?N}0xSgl0{2NHGJJ@OLRZt5RFZih$1B(+I9+RT@{?W-@Xp-x2RErId;f*2c z8;ze%ZF`tuwqw2C-&@eLpLajZZ~HMy1x8A#0o3xPY{sFF4Z+3RFD=@FqJ>L#=zJM9 z!aG;*W^P@0N7Rm1$mRhkgy>x%v(LzHiqAMKnvCQytv}^2#;9t(QTx2lYMQ?AK}<^4 zUoHJ#QK#vK=WMv5fr%cQg`D~xBkhlFtHJm{XbSMrgYm@ISe#_6PK6>hIi~vFP34jY zK!j0F95kXnNee3;A##U0`3`l7aR8()UCZgzf!>d8qmvFmF#TpO1V=3qv+2unfq;it> z!D%g1Bd0s}=y#fqX}KH)=ZLUgLkmTN2*TS+{MYWP9X3yQo2(==qmzLIexsPT8MN^1 zep99?XI-219r`++YDCYCG^_9hq`^{lz%_+(;zqKdDUG_U&k8;`9!W!-wjXp?Nw6@A zlhf*X6N<>5%4nQ8Zgsk14nhzRqn4GDvBq;b2X6x!f9sir-!+09v6ZsPHPrzo?AZV+ zwDEo%yMo9zhn089H*D~JH3{ut5kNXV+1e0uoPUJ9)jx}Sb6UwP5uD5%7HJx>om>U^ zUov1|y=V5x&70%x7ham<7TdkC#gtr>ol*V2SW1*0M>wjm#Y(fmU$hadBh5Kb{!(FJ z6sKR*tw74g&jLX*A<|c<^Vra!g-DDrUp#I;{VI`*(snc8RamXLEZoJJN1lOCZ_~pt^!Xb4s_K-3j(CB+dE5XwYBlYEHpHyGW=;?0)hNl+$diBa~uYJYEl3 zxC8DDJ;~x~mo7hy;#{^&Y`ziPs)+bfN?ViQDb>928E5bt7M){@F>U4!F>#+odS%j0s($ zY~)f%9+|941+)7niisfi*TWZQwU6}+NK8Yzh%hi4(O$FTiY@r(>mjzoC7ec7ZopA$ zocy{{=CY{Fohbpk$(=x-4zXemZn+fb+O5>uC~rF3TS{G9PzuYl;_>1s18bAveNGD> z=0aT&QUh5c5(k19^70aSxDp2Lz;O(`SmdfRS*P15R?GL2FvQL$>+h7eGWy>>QF`7w zPycl04QQ0higP_99RWkpY!&O3*%fi~>cAh6_`o@<4^5G)l4sFOH;B=G?ER??u-9T_ zJ)wISerQAdsZu`8Qvtu&mYiYZnL5_=K*M4m<{VAFA7@YhDfazSj`I!;n>i#j9mgK_ z=a%zK!3os?-p#bI+jbvbJ5_5-<4xcI251;K!Q7D9(3yl=i+pXmxszJxyrN3=rbhcW?FJAtd6==6aJn57lBcm>K%73;-zm|`rlL0U&fuPi*Sp9 z&Jq{^Fh>e~RmY000r7L7HehAxmV+ zU=THvm)YQ5QT<<_ zkq&^UPhr3zWK{(DUr(e{N=dGM?T4kzf_w&dMx$HOEn+*eTE-5bUiqmg7GhpQKv#=Q zDv+TZ%H?)iXCcyQ*%m(vexlCkrvf4*UoMRGKs&M6P8_(+V(Wetl z0>y_WOGh}#rO%`vd4PoHQHYSdsEFky0(no!h^|~Cp7QG}kshBG+0hxcxcnKj@9uS< zg#||wRh^9G-2dAKW7ppuOb+boszs6K8#A^n`TPs8v(@G+#6sB@@;(#Qu00L`dZ9YnUwz@2+YMF}y zDe@!t#(Q+-_|%KL5!TOx#!wx-ay8rZklq!?4X9jepSam!mI*l$*yqBv`A#qxV`}M^ zQLqCY89kInD^OwfaXHJg=ls%yqzTx_I8;pVX+`DQIVg1+Su?d9G$PqWOGagUHUqML zg#HMc;k04U6ZJd1zhn+;?e7Um3j=Je7XA_{SW1B|TfImI*4;qQj037-{TOSF_z}l{ zX(E@|mbt+Wb!>8yBwh+W(>+`p`D#atn1nO+_3-D*WQa~2%;O5xGc!*?T>wu>MTd$d zoQINLppUy6nBQc}+o6V$bpq9(rECPkh#@$9{q-c+B|n(Uo^;@WY(8$v9RO@n`grdK z!(^xIsN#Tv7blk2yn|WNOVRuG)$wjhPmOR>&f-iIolemED;b?-4>hD_8V>xbPB zshBKQy72Q`3qX;rH_V8w_1IFjup&v0mAVi>HMlz)w_#=>`ouG*-*7A#6NA;yCiaKd zExZ@Y@ODCi-#v_*Bs@;iSlr@Y@Fj3-Jr%&SeB$hTvGX2j%wMRlbY|BdCf_$zjW~f+ z72OyeXt3k89?l!}1N9UoA*eSYpxV=x^R;B9YHw)Fy_n~FIdZ}zn*~MB+HfX2%+(ydAQp1&)|N!F=O%3lk7d$#nBh-!!9tsE*gd|BNe?@K9^=B0Z-jvo{AL-?j`UXVAKbDno8^Pc?VR}szyfJ+;4Wx$S2#EWLV(?Uvj1^`(6y2Gs0y0Q~JfHUNSoroaczO=OTo7h3M}ND_ zEEaMjh*~G2!uk##DKsW?7i`lYCmMjD#Vn>iC@%lX2(224`U{AV_=rQTx&;hGVjHx@ zV06FHcOC-ngxIVFg04k77ff`!{&s<$rFZPgWp!B@QMFSiw${ix`s|~i!(Ho$B$9-z z?bG-k2Yq=sXs0S`MYp!Y=;_l=&*~?B8^D*8bHWe9RT0Fha6_H=hnIqN1Vw2@;hH{`Wu8vejF=~7fH0>YG?KNxA)|hf17QTAfFg84QCtQP;>ZRa+?r#Qh*idHNN&$ zYUDjRZkjOLf~e93NBO1t-h4ftn7<*Y0~(a26&!V&+075TBJQZy#~rCZ;Q>J1TBj}N znIy#Qx>>;I{n;m1OCp~(n=w6%@a`V7J5t>KY&&NwWcEr%q1I3%o2isCaAFIfP^bKq zK*k%%>*ZmssD)aKWLWe6+>R)S+^txfhHG7z-HqpL`as+?d7ve9z?t~eNr48~8N~R5 z=ubH-RKJ828OkzdHQ-JBRe|N3+a_~OG?Qw%J1m5Cj@bMkxTx^SubKrPeDg-#m=SAP z5{F06tM7*ybU$2nlF^aG9dN#1y)CloBWxn9gU^EvCbE<0YWFSWKbF8NKt%^j5WFJ>PVb!xoBb_fbFU|@?Y?-xe6z&lX78}noKQcL_z zCbOZV83$R)zd83t1m!9?_4FpQR5Lnal{xWo$y?kiC=I^#f@p5j;JTi&8SCmCoiCT^ zhjvEiQ-9p!gIL=3abfmC3k3R%@Ib)Ox_WS2f0f1$ zg>$?tss3`-nxmvzvy8nfXWbL=y>-z&28%z00RFvL`QJxo^hYdN<|N4?R@5?^%LDhK zG2wUoDZCuk*y!ogupRn|(J4g<78CSf`T7a(KWA*p9VI0K%jp<1Ke%5nON~Yi_-1IrL-6|__C8#t{tEAXV z_qB4b&xw&c3AKHG;O%7*aJi|dLu{0fJyd*q%>2ciiKkfe(k=;pNa~y1@{v=z$t_zp zJ$4DBDaQk3@U_7xHcnZOd8OB-;C!O}baR`(ag+$u`gc?*sr%HV6!t`yX>K^TbQ6)NJq$2EpSnFG6$)6@Y!)I_#V&7#nV?M}lQu@4gG9D3gCFwo=#+ zOTlluQ98Y)BkdHy^aS-vu^R+YC|>yg#-@91VP!XOY_Om$fB|q`Wgc za?1TzmXv^!BG4$&JQ^~BcX8(v%UBPAm|LcN?et6qxhEDi0%Dh?+Td6-+sc16;tl)% z=q|&C&MI^wCd+Y03hGf`lZIe9*>`C zKZTiju}*u5-In8_maRScC}s}q8`}s+kqM=N^1nIIA!k8*h=o`=D&Qdb1z?Hc^yF9P zK!z)hVdP-c&wK*E*FtFW7n{d%NO6bH7eF4RtNkuXBW9&7tInQN#AZx$tbme=89NWA zA2;ta5ikdNa3|QHgNLsKI3c9e1S(>eWN<$t`-GcQx0l6i=2Z8W3UDW9_bQ@)TUS|@ z^>L(wnlgo31>+O_X-u;b{;ZqKxkm!%~cD-%}5nhcKz=E1J8T1(7Vc*(V zIN%obu3n;6544;w(y1qXeLvExtHbg7!=-5G^&@o01B8_XLm%VHWSh=t#R2rlb)p!i z*;0C9G_xsZG-!gt#mpKgZzJZJZqs+>sX!X~C#jxG))~X(`(;EPY6rI9>vRDBmm-FV z$5LtJ$x0Ad-9}3Xh0M|+#m`f2BKC##*e?w8E2VKdTF-TOjE z1Td5CTMV(OGT>5zUPQVr+#4GAqOob$8Fl2)yH<%-Qf00@HC^-T#7uhrpQzr9% z*dty6F~rZSH07pN99J63^RAdjmij@{!L?-5kCYABdE8nWj$6*-yvG~-$bamw$lEAA{=DUeX#;w0%PrTsY@N_;_Q9#; zcjC;ffeD9-dU|2;zof<>&iW5nj8F!3bx%;xp}q23p1#}2c&AzQgssI?4Nrd~Se_cC zYM)sCY*N(lfhM-rQWR#0u_0<=nPA&btVh;QjJ6WJ7z5)wNPDOi97Yu0 zI=;9ZgCXwD6>{U=fsuS*)%Dd1UhW=~`@KlmRYMe=0002yL7s+Wlw|Pl00B?sKhL1N z!f|y4`-K3rtZB_$W`rXqAWhdckXD5fkQGWAg~pmS;p#-|LRq`MPV2ReSU6zOmi`2Q z=*Hw*>)P>DfE#L(AEMD;~-A_UIJ? zBWWBI)J>xlCziL@e$g>?JhlRn)@ObhMw1Tm6B*oij-Bz`4!&Hc;nJmdq;3Mc;fE!1u8hW%zfItvq4oN?2S4MIt$>yGmA^FeW)+$VI zT?%&*O!<|o>TzJ2rW@Em;@33{??4J0Vs3qKr)x)yJ-qcVeeGC+zxMA*>$2> zKxPIu#rZu+suEHc;gX`wBltQE!O`391ZYEgRz8U}WFt4_3MVL1@NvyXJo$5s!mFJW zH2n)gS-Sq>9>G=geomrkIe2lV8)^=Nm}x!S`A?Jwu?y!TEUUfyzn6f}`9t8k9XQGc z!R1Kk&F+1-C&2=(Gr*m#8#T>4)-w=ExEQr&_rKJ9EB%sqX(9hfG10OxhOh7i86o{b z!#AC{lM?-UTux?{5;JPhws;<`%UN0awt(%HMdL*?z)jYqLzGE>bKrPHe_2U@wVStP zMh*O;WsbN&pMEv+^-yem6+#t|n9@W#QdMO%CUYs78gSAkk4Ml#XglNHw0`r9X)mp1 zZ;jL9DFBo%8hXJkbz+p*lbi!KfiMT*7^}Qd*hW^nJ!%BF21=rj8%L=aGgy(ECK)L} zWlbWFBuP0Ic17!M(jq?G(sq$1$>5?NpyEM2FDnyJSkh|25<9P-!Veg;Z~$CU5e6bc z;e@(?tqCIzd&bjVIgdZJl1=%do$-X;ezPg_+ycj==yyz_#hB?IIl+i(X|fq_iRUjX z#|E_y3GRD~UGK4VvIQzvlxqnyiX^rl-*^o`%RQ+XlAZc_KT2Oq^)~=OND9rhK7Ki5 zW)r~ZbQ^!)FY&E{umifn6zy%kvE5gR{dqA3y*#)*Ca#%d!x9*)I9dn+9Wo-Sq4P+| zP|WLysiTa|(JiIGg)fu+Nj0?gQhVMwx>9P60%XS!pApaT*O(7;`2FpqT~Np$D~R@J z6lvbTc)lWFv48s!F-8?oKL(vYb7OW!elV*KY};i;^lrP$&nK+XQYsJ>>7=Wjv!qN& zb4AUVwnfn>j`?zA>A@uA$Ci5fRBx0XBfH=i4u4h?DGmrh<9(n5h3e+vD<26o=>Uh% zNhwfPRIukT&EUV4AJZ7Bg654$Suf|BBn3-U&AOI7Mrm*R$PyNZS<6OFF&51@7i7B( z>>j1kQ|PlP1>R@bvZYno3PMeB#x2lNPru$_V)MQE0-gP$nBO!J{L9VCLu(%7Mc4FEcX#~87XAa^gAI1yclC2P6H4n|)r?QZ9e zzTD#zi3-^0VecpN^$x_2nq@MQYFa5t-zrr|8wwE{Y`;dN`+&zue}lO>zb&?9iFGBn z27r}x0H^y}eJf3x{_}2C)T6uYw*lez_0=W{a6TlQVC~8xie5hW?LsGNLY`nQpcQ5g zAH1324_N*@xj9%!@NC-s!0lfdr#;ONmrnvnpg21_+J&~W*u+) zwf=Zrb*RiP$W%=f+`-mMmMZK`6CAeAh%Fig?cR?893Z=zzZ8=Q_cp^MgZr`_OgagVG3kDnrCTTVKY0sGxw#_n%A7jTVjbPDKr~}W|7vjo(0p5 zM1;bxBP}YtSWlBdx8pM>oqt6N=?DgaZNs<2w0#&BgN8oAV z3$zc;rnqzAk#GS3R?%mx!z-dz+;+EKcy9amP7ij}1b5N#+ke2>Zs|y$Ow2$XQgQR& zECuLY<={#r0(r{;PTw~85@h$3eH9>qD?(&kF^yI@WH@?TOxozt*qVB9_)FkZO&zfa z?|~H%w*SxMK|HGkwBGd0DgtL5VOg%`_;GY3oYNN76_>kt3K&Z|*1qE=L1`u(K*+^U zLd-{mjlNPbCUOl)H3I$f<`8#pzk9VSb>AviBQ-rA8)G{urp`H!nIvKs=#97g-gex@ zJ;eoXOpQySoF8CW2OOx$qC#em|8ofeZ?9_aY$-ymptYGwV=p!OeNs15>(pf^W`* zZ#0G+y041|q_wNi&^5mIrnUV7<>RP0*ev>uP+SKl9QXJpQ#OzEc+)Vb9`ndQ{zUJT zq=BOKN|#2YC)&i1)al{qo@g~DK6*7`wL!|r2FEAYSYu-G5^rY+KkjImU73Gu2eivB_5l!IA4tk;nFt z_eyRZ>cT46zL&CCK-n2|KX!RTSbovhOs~rsde>sWt1j_ zJY_iYis*obT%)(H&H*;~OvBDv!MznuENImDE$&pE19K?Rwyk43*|F_p$F{j++qP}n zwr$(CZQH&%_0GFh_ZO_LUR7N^#vJn-66+&5{sI#)d-tJepu9`8Cp1DeiihN?F^p!A z-@Go5Zhq#quP!(4>dE6n#kase9T_VY)6Y@eJcoR>7+*`NHJiuwwlS#Y8z#s9Wq6eF z?DbMWs?}mIp6l;5t6g^dHGm#K5E9dDwiF`t=)Cz+HC-73)*~S$VHgXq zkKL$fCx$>pvb0eG7rnk+oK2+3&q89f`<*S8s13fzJClIfO@{(zZNGNw1WSD!k@G!G z2*8+_#x3Mn7}C13X>J==TU{*)#;9;o-V;*NtV60({d7%Z>si_~RZ1(8l;WUNV=px0 z0h*NX3!d>!P|a(I>d{x4_Jt}mF8LUm57G70BC>|^{97Y0AT3xgqI+r|Tb-9jI>4Yn zG-K5m`76+`?h*=S+{~>}^C=R{_|zIT2a-Lg`gkU=8lmteW>Z~_8%dJ9@R`D^+J+Nu zQ1N{oZ1l5SPOArU0j3_Mk2XT4U5==YPu_Nj0 z(m&}nx(@aOa<)W_#((wsbPqt=|Fg@eFgZz<;098{2zmY%YGx>au9eKUPEWxEV1UGo zoKYfA`$9`*0dONsp(!!-tQ8q#9l|NZ7u`MQ?#`r(>9UENt|;`X(w%x09PupU+^Z9j z?Y6MQ0~}mjMc!7gyLh1)&1Li9&IcgbKZ-6GmD+sBt+WR4UBK61Qs~kU6~6(16U;%Z z;9wxiVO$%0@uy1B=f^!Yb2AQf-@+7ib`rj|KDf6JK5-@lCcRj#FCdKVSM5aeXOI7i zTq({U0H65%3vz^^68ab z;J{?%qi>fhqEj#mObGz&B$og+$KnO{k_gH5WgIDmztM>Q=&!T?FGha>N@vYxvH0Bs z6ZgBv_{2awW;@)uT;s2d!X_~PROG7&(}&z+%HT~j^Tqi^w)i`=rj+bHHZm_xXWnwU z96+9VqKc0ATJ#E9C7{?d2!jSae-97@%)a=Kzyqx~kvge;hn|Ud%=psh-qnEnfDmU* zrtE{jv8qRf9V!`C>WUf=?5@cjhkj(1 z+QEi9NBkdn7KdJ2xJ2~sFq_ss;+D}IsbG{SSNtfBgdQFzE=ipX3wsXWD2Zoe4P0BU z4-3xt!uYkKH_PdOV;W*hCUIlqJy5*=_9|Y5kEj4bTwKOC-Ix(Zb%3e~<*7!{{YsaL ztiSQf$$iIp0nR(%y*(XIN{sBmUjYGP^*pe{2CgH01&C*j1x_{}tK2uTQqpkyoG%di zi(K1hGU-<-B@}3=`)>pIFqvd}9HRtbo#A#NgQv8bGJHPAu4kWCTXUHz21~CaYRj9b ziX@ry2oH>`dq`E6E6MncQ=^^nE#ju)nrBu#G`Q6CH9^!}twLjF73%gx^LOWeFFs+E zlL1r6h3Bg`s{KG>0^8ShiH9Js(%heh;~(1C0eA<;ADj^w!zbK9u}(P4J`?-~Y2wKh zj+S5eq%60akwS;=VWNaJzQ?UgKZdkQ`qbsv$gsci3XPh3Gr?L*cG3{y0X&~*VhRp< z&A1J+u1=D-NBm$w)m#WT=5t4eAF`?fsp|^zA4#Gsyptfe>eszB0x@;o$hrLD=sq}f zg0Ka%>Y5Do?d?ZV{3*6#6q=87%`i{s+%?1-4yS}xMi|sVAGoSoPUu+-z$FoMB|VG~ z9t14P3-lmvR|YT?R74Wc#SQes7DY7SV4&ZyAiGT`bJ_Zy_xRgARr(yI*`C!J?7?pS zZG#h=e{8zapmdMT)U}l_;BA@!@{F8pt+sU`SuMeDmAFHQtM8UIRX#+c=>*&yLxfb} zQ=r-kOOW~5`FY>_T8ySdh?oQO)2k9yw>5Ek{<2-Jfh^&*+%8Bb!Es5Dlu70M7>jK4 zR`5v)kR%?Y0R-3SRjWs*F^_jkoH$j(#C_#jmz`FxY@1`Dl64Cf_3&kv-)>9WHC_F0 zbdBceO9AacS+De>NXLemu&D5&ckVn@InX(P1wSLmDNrz}IpN8VDE%VrUQ(b#=+lq~ z0bNu-!#Os~moXXh3Ep4W2PMIGT+&?mp4jWW*R{|dO}Od8xH<6QR%c^n8Xl6L&GgT% z>G!3E?OTASjD+y`(x0D;!_kmWz^oqtJ0ho_pec*EW5FI>l6A#-ZqEM#ZY}0M>wj(o z5uQa9HhlW7A{A=3Rso7@tJy|>U0`uc50LJcc#+n*ZS#N!iy$%*QO58;`Mu#ezcQPM zg-o0bNZ9s&a?0HOeL;SpQI8B`M&0E521c@Q=j?9%HGT9Wwk*A>p9fJHusVfW*E zq1j5SBoJ|E2K7}Qnd^HKK4lJf3Npxq=RiJ5+o9Tj#@3 zi6oJ&KiFRXlwRP@A&R=cgzc8?o(YczztXPat5=K2&*bOkqEGNfq4Q-OC&W6g^O~n> zVkhZ1)9Tf9e^m~gL?b-c*}*GHS;?T-n4c@5{9ye&Ww=Am--c6XH}*& zWrtxj=MbNi(|L5e9$?1y_DbkoZGF5^B1!pI@(->wEPsG(2c~ zMv~1zn~v=u7J}ZiDuO&9s8X!+Q)@Xu~i?+`5%ge-}PzG#^mRTMRhamuaDhBWhMdOX1B#+B1 zO#&=Kc(clndrA9ujkH=MFHp4&OfLile6cDF1a$~mT4 z6I#M}gw6X9u{-JholrYs3;k$#{e&XFtdMq|Y|t=?0dTT7C`s@SwBQF+Y|JrHAP z4w%}GceV*KbA!RfZi+GPg^-zLFx@4g?bgsf8S*H(76PLwtx~$&lWB*}v4)rZK6Kp* zmpWsJw@c^4XWqf#C9f%=0zJN0Y3m4iEPuC@+Cw?lx2|T|`*&}jO8GuPM{RuEZp=1h zG%(ptinD^eAAsaG?+GmE` zMz}0u_bUT;Sv!$47(7OiJ6wfX_@5YOM#mhzA41F@eU$SBRQ)hq)_vrPz zy<&RG!P^+$kBj%PsMpGLy)rH`G4TF)m%48awP)?ta6N4ita=tYHe4pJ_7FpI%oIIu z^7p2)ckh?%YzD>4O+*Y75%AFjJjsX4r{OyeOr59o&n`WOV$MJ-ZdNrkfdb<#gmt_= zY5&>}#f`i|(iT;{WF$Iir-z4#fPDxeQp&i%ByOtF4 z{ah5fVppL;^9zP{X7`91r`m1v;2D2Fe3Z0i&X?e;o4L+7zIZ$4SvL6H`kbN6q+-bxjthDxk@l#RPhR`HK)O*HV)ih2(2_`$W z^C^lBriEuKwKp-ZnNbH7eu|513=WUO42b8t70PxE1_`k?Af=R-B&GhgtlHxXMMcX) z*E~2Q59X``>mR&rE@|pIn+-T7TQ}$sFxvcF`Sd*on*Dz8z|xVnkW{WVzK`g^Bqfi{ zYcbpZg0%3Uw+YTybSMVv*6E7z1dq#e-g&!PvS+nirHDI)kT{2AGcw_9rKlk4F-r|9 z1?74WY~)GAmw7_IQly6mgrt=DkMv5_ODEGU7goG0$TrHsS*kpP}O zx%6&C+->tvUTbh!thm(5n3arFp&!u({#r>I zKO_%LCqH^EW`q-%P*+HD*|Iu*tI(CEyMTJ@XFhNa<;CQ0+XM%J-Ht^|pZ75_@g_0#HfyAD9q#o%KS2!iKGD zd**us!Bs_z%g}*|kyH~qRvdazV?46YGh`vKQ0_*}sGnm2Z1Uo%RY31REzx0ei`l2X zR63r?r0P~*3uI4xYWpb^PCpFoon!UN6SVQq4ZH}AAUS{3Ojrf9KWR6bI>fD>NrlB< z9GaQ+kK=PJwlp?4`5z~qh)< zmJ{MhVg}LzKV4xe4lL$dg0MQpbjwltmHH}qcTywa2Y@inNZ2-l?6X-p_1bw!SaxEE zW>xJjXz|1rCeR#d;sC6KeHH(HGn^}ey{Xn4y|N;}Fc@%6lE_qM^=u_t8VbqzaFCt~ zzA6XsYgtR(%uqrA+(5a-*c@P##i|kH%gT;Qs%&&yyKlg}xgnncN%y^s$dPogEaB-j zLp2{M^jMjWIWzvPa*Q)RMCl>LD5g~DfMPOR_Dhj?xYI{G+c4S>zZ}J2q0l=?^usMj zC*I8*r#iT5;>wqPP|KG@h^uod4u=urtO<+Loj%p(5XH)XUr7Ukj{aKo30UKkv9Zv(V3CGgnI83L z+cmXScaOTmT54379B4z*?XI%JTItyEC`ZQKZFr$3a>BaZx3*XDOARf^Ih2 z`EZP=G$wCz3S~W^R`3R2qJ8#BTVDCLWs3UxY4#G^ajp5R4P3KVX}hSOFYwp{I9|IS z5jDqw>Eo(u+xwz44W5U6efC7m8P{YSElpV(!B?JMpVCNpQ%$aJVZEW5ri~}_R5;6| z%D&d2;k^Hr*U`&s(_%K}ySE1!mMYj6@RB{!M)>plyugE6PL7o`M}AXg7bk|OKV$%z zId}=#0-Eu(#=4%ncaBh+2x+-UgL+iH4GmI~wET;MB(UEAFQY+CQcY{(x=h43O&gl_ zcAFtDj0kq>-v(^ds0i92@Hotp52NjqYYW?k*o8Fz5E?!v7o>?27Ga2LF)E1&%EZS~ z0zrOt5V7vY_&fZ?FcgLH-X<}Gzr(EbNmx}H(Vt)$Cm#9SIqI=Qm(HZmV88sPsX_r! zfxqpRb4A1dtWIXlQr*o-@SAhRWI!1W9$LACCdDzaD)_(tVB(5C2LD}!H|{viVm8rS zqhv~+1l{KU-lVSYer7{?wS|9I73v?npeIZQ_m3ZB(=MLzFDnA;dm&aQLtdL9xS7V2 zmnvxu$!E2BiZ2ca_t!~wi-j?;1DLe{TB8*8LLZKo!_fXl&+&*MZS;Kc zZ1bTgnuw{JO0c04Dgli&SqV~T7L$pmbX7>YkeF$<$GZduo3{YAZ^qU(90W~eJ^-kdU2_8o+-yT3Zb zZ|R|+1nZ8QZJD_FyiM32frI=b6QxdrKtcYqbBFWCu6j~4Jk~oFh0E7c3F=FE_Ne4h zvYASTLx{1yrRo#NoEtI&)XT*kOiQx<($EBmvaU-0GXBo%Ug-0y~ z${gHUL?Ou#80JP5_j1jOoc@u!y3iI*ybl$FUe-Yv!D{^ByzYSUHba~|_nG&$Dzu}T zEd6nnJYUErIaqCWbm6E+X}k+2VRRAxdJx(2M$5gD7Ir&3n(2?e!L066(AI$bSp0Pk z+DwI|mJPo;WkQy@YWB|=BQ31NU^CHR?e1y>q0nGoC-yf|nau3@6?{-6NiRE!4HeBY0VvX~N0Y$kx|p99oXxW*L#>TSBpJotO7u)e(qSvm zkM++kA@jd8go&myqYXrd5z<_~kr@|yPNZ8gQQhycs0d z*19C;-C{I(+9KJfD}g!tU``7%KIF5ttIbYx&sX)u=%~o6w;AECQcZTaL4!zL0}ktZ zihcK}mF!2s=0*c<)3U*1Bzp*1X1uZv;8Pu>4|RPqfhNvk%@OcI2fIJ>*;t!XvLU`5 z8`mG9O0V(IDcqev11+9J?@hx2QD+O*W-+*)5!!nw`cbp{!IyXv_9nZE`Y-66mL54$ zqHe;#Vm489Q3QmMrIGrwOk-8}FVw|l|B7e=C07xfbP8#+CP1@MXXXa@0{`?Zp-;s; zXwq4`dJlJKj_V^kCraA(@pfr-+Aq_N{T5Z6JpEO$I(i9&jhpO1f33O{Cwt_b{cb2_r{Uxt!v-d|CQC| z;8oY=^-@43>vAJiScFyvR`I__S(njmR5^~RieIgs`e)dgdnV>Am%;nHO1fZW;k%FQ zItlqtx}B3W*lY`o$i;go_=eXHO%Gn0{wk`XDO$*-s@eV2A#9cdSRPfdKfYlydva3iCQGB;iefat+ zf1IG1m5xoO^yX5h@cKK%8>gJ9&X+KMAJtVL)mUymq#}rJ%-bQcWs2x7(h{42=?)vS zLnQDvkJI2Q&sj7_YZ@mTZ@Pe!11ZS5q*f2$E!aJ2-y#Ve5hD2YV|ygqm}tkIy6?M> zVvhwa8vUSGSf``xZNawbb_DB8AJx$TH7IgNTv57A@yOqNP?~&kAVMe? z!9u|ys_{CR!#Y%Cv#>%gGju5?lbzx44$5;1KX{KG`gaV?#{kjDW6V2vna<}XX)S)L zLF4@L2AYM5M-?WS&%>%mypfQL8`YL})dB0Za@oVuW4KYrt!3_$8TqZZ3{8;H^8zDy z(it`jqkkb+5*fPaH9Zs&>A%$1zb9qe|8RC4STNwJk`$+vht+q9Tvv&YG@YNLqDkf4>?Wq{KNgyc{{<5i}O2YN7BuDdMdG|*+HJl$tjXI9? zfs#B?;UJ^cwJsln8z8c2ji0_aPAxK6=OH(iTp;#)8GGH(lEc>?b8Ynvq(Jg*P?318 z2ztPZCE*KzvOdM*NDX>Rqt(wjCaN3f{XSB@j#;yjGgH99RS;^Yv>K4_CVSU@b~bfL z$1_(J`;pSL6%HGMfI8rAZ0!Xe0hin)_{9D3@ue2S>oPV$Xjasv_wJfyHy98AmJwa< z)`uYjfGtn|ZpWjJsc7~sY_U>kby=ESh~U}7)*D)9r-=lUpUzZM%|N24K~x6b`{wib z78-sg!c{@pB*myPVbw!Fs*u^`u=@l9WH*{RkrF!(Oc>VNBrZYaewXN8vAY2{oJX?8 z)-nDsA5OSEw`n*LW(a_o{xj@n(#tcUi|;fUJqbCfn_ zJ5ZcMOOX|bb3nA{OQ^x2>p0y)Ay7&tiz6=H*~~9e7q#PHGWN04qGJoFaL?%8gdNeJ zeim~1*D2+j?1}cgLo_8hR^2M1CU62abLZb%Atz^T{VWuQntIm_Yy#}k70FRyPZox4 znMDJjQOU6}{YaG0N3I*d>J}d`AaP5{sZKh;eB_U0oVgK=BB@Tgqbk%HcZL-PK$F3l zXAG5h(A7==M9@$&UKE&|cHG{@Zz1Lu%8j&T(>t6%m5 z{4W!D4lIWTBsl7>zz1C|%?57|?#)fDt~jh14O)<5u^PICB;?^e)`_xvB(ZXb@TT18 zhuo`TgKuBo$9)obXkU^hmFMTAHdo8IO|wnT^ypFn>JtcXxRZ`QQ+UT0(D&!cCUf3~r2#p|>202Q} zH%3FdL;=#gjS+ch`KS)TH;Z>UyhjvcIWmuZL&sX?$`Cu)={|VhVj2HwFqX<~3!PdUyVn&s%>!__8N!q+&;l7m@;V27L3!=m&Bx4OzL+ttxq6 zw`=okZWcX@h)$>d#e(ncwbl5s<(tNSeFnhMV3`5s`dHjECn)gD*a*mhv{EE$tJBTW z^ws>gg#{Qv5)4g-(f52AZZtnnk`Wp)g-vVv37Z2ved)sQ-jy_3M~pQYtK55}8w)$& z$q(~mp*zKsO3DdXt&g>G>~ z*sX$QEE3f_#7}HdH7cR)z_Wjg36If!CP+O&cxlR-*P7|#P){-U;pzHKE+;=Nt<%9} zfhi52z{O$!mv0_LXer+x{PtkW zey9uGrdnPk$ic{k6C^sn#Q!Mh7v1>-j6#7Mt|v8F#N+i&p6JXY z|FobCDQG(S4T-SYYHEnPqFN!cnn`QR@a^PywQaik)H=5WY%Pu>ATb{M>N4j=EU~g` zHLEa(x($Jd^gNC}{{yy8Qk%g8JS}RP6UCd*6cN|y9%+>ZNzyc4sb2CMdX2(@3Ni6eTV=tFdSLy4>MRO6zCns1P|#@&S(XlR*~P z>%_h(=R7m1PuhXmgQdIas+m8@e}XO<;dk(Di=PBXy{m74KhAp(mmo7L*DnP9xR6H3 z9BfNO&I(HDB~`4{Xd6D&HL7ShWS3cYywA)gB?po8*@n;83e<3=pn^5n^{N`EVvn)> zy*v>z(x~VN2-#+lhF=lR4F;LCzh)SM%((bi5D9TnVCKeCo4o``+0KF(bD!Z!J>=hr zl&V-DSkhKAwig^d7yy zT$>BWF%*SK_Dt;mQ&nf2BX`M(t0%gQW61MDjP8Q2%_16%q0y*~#&)%|amjzzFG>>J z`KYGwsvh#MhW+qXH#?t_liFge)}>$GY?IR+)dNIgn###OnhHY%Zc3)$Ve{0fVt(nB zesxcozx5VJz{>B<0pm+;8^-YN#l13El*BCjV%S2S!!g*prkc;5Ia(3@J=I}O#)k|) zN(K2&Nsw{-B$PAj-P6ObOw>yE8_u~i$Y{H%D)} zuT#rGbLDYT7oMcQtx;LfOSYKq86-xP7N?DoH|2;BDn>${Qs*~)F3Fz*_unEgAWH56 zsSPTtf2!av9os?rjo#g51!nu2!rGK@<;x^%6^bfZv^$FISZMHQ++}Ad^O0u3i_uFz zL|5xOI)GGU32k4!s#>q^J0!iZ9+mVjP3}`lG*-F zzoGn#uDV75{5I*}N(%KWY+%P@PgE?XFn^}2ZZ;6?M?~D@hCsjpAfvUh6~*{5I4^a- zB>L*?Ojohw5dy>2>Ju+riq-Vh$2b`#KLtQ;6# z!8jt?z2DcF4wysppZo-9O+zm@mhZhHj?ld3U(Yp8#X6f^*3c5&Q#_+XBWP~JLmdxb zY`*h3x?&nL^edYJ3C3(EZmOuHX{>9Z`pfE460=3IygOJn83%R7$t!E&}Her^^?A6j*m6Y_Pu>>k3y^z+SjBvN{ChSm8*G9BWfgL3v` zy^Jgox8i8tHbM@xXI_lGr!e*yp1fStK8}cH%~R3%Ik~D`=+~R4??i{b>g%C!tz0%` zoat&S>oC(eJzT`fOz`@J_fFbSG7`o;N7LzJrreZDsG&eeOmbZ;i$y=rd?2{3JGXkY z>m=Wg*1Es|&oAT9tsO5!Y@)O@wr9gHR^QCG5#z)Za70$tnM#kpNY&sg!fzsQ$hu`} zPr5;*A1}pA9~rPF8SVoDqf&=R;m4&MG)UZ=g!*9L-*!1zSHiJJ&5oiJJh;#~fb5TQ z+AY7~6GOlpy8qoSIBx+g5_frffmV*@+bPpc1qJHXbjGO;k|PmnPul&W^gn54&I{la z7}#=|48S2e{)E8G)IF8frc}m+6?;~56SzX1*}8tv={}YzUwj8e`b_6#HF~v30sugw zXpOk3Fh-`My$ZjCi zy^qQD$aMc;2FHU5LPJ1?HI40eVfD+LLhfb*HmhOH^QMLi60l=YE3v=`EY>cemuE=+ zeIy?Urt7mVh^!||OD#w&Q?5jZbBM@4(wI8VEOkiV0&nB<6Xihecr=`wr$&nV^cSN; zoV5nbJ!w}>1)Wc2FwUdH=DFhxf|=r1p{0n(&iLm_Z_9akDw^qdc<2$MJ~Y=-?y#e{ zRMlJJPpCeF)9;;6WY1T{SbyX|BgBfU@GJd+lGXFWD#-TreNkdRr0Nf533ndO!Bd6^ z^2xv|KR!j*;Qa~DA!tgzYaNXhRAJnVZEB}>ep@(1Zm|CxDBSpDhYb@wmw(d(vDpy=JxcZa+IN<-*QfPi$=>bdQaUa;h>>kp2h7hj* z1#m-eD(UGGvKD-pCV#vbh6ZE_O3+v2y;Ho`BM?3tMY)Q{)h~M(`?|H2q2G z-wmP13o8Mw!wEYYIHNoTF-~LA1NWHXn)u_yA57}xF#&7Aytln*s42&K8-& z_x?*3n<_+-@TnHvnYTd9V>k4LQrmM^K!y?Y6tjt*%@v-~!0v_(zCpLB>%3fkq%tY{ zU7+NNhdPlpdF!(_B84r%dCs>2{818}5H9s9P!QGHr1Pz~kVOH4Plzz(4?wf3ZWr4F z?-;^RdK(&g5EGUh+pC!Zp^QGUDl$1u$8nTyY=Is*fe6Wx`4wDPF#L{kLn_e*S83<2hDu=89i9~>ifT7tl@c-2oM&~uIYFmU-W33=zE2R zVz|?vvQViMj#OKcKAp-=1^tx;7!M|1v3VPNPy&a@Qg1tp#6hb)Ae^nMDc>ZJ#A)32 z$#%_ajvfK4gV)w2=PskWy<9OGfk4{2t4`2uV-%SB=Ua7l7=n)9IZtlhuT1wgpOt~w z4P@xcM@a&6k3dGSi+OU#v;Z@Lb6;(TY+BKWeM<4{8IWl-yWamc5$>(>@(O}=9a{vn zyYWK{E7G6@cM3zUBewX{ymg8|9DvLbto3HLT3?=JT-jO0nSVD3qQ&XpH0d2t=wtK< z@YlV}uV*Xw!w|L$B!gy7j`fqlwFl~9%bWE@q>9)w&~vqKI55TJAFgyWaI&zRR6w_Q zyZhqyY4@jofe#YMDjvleC9Dl(i39|2s+2|iGionUIvX`}J2E+PY3&#{bjW0^4~H7u ze6YZB>CQnwYZr|zvrJy+M)FVBDc7(kf=~WKG(fg23|hx%(6^C}f242#sZXYy{Fi)F zD0E=rHP$G2O93Aw<*I;TZ6PzI+nZ?3#+4~aMx2yAgo%VwTnu~9 zpckNm&ZkpU4AZG`u)vIVMKN`yq;`@T%+~>ia1WIfY8Afe1l8o#Hkwq6AW?I3Ih8b! zQilyr_YJ%X5j?hV+)!GGD6;+0iMCuMgBL7>W0${HV4r!32dQ9!=g?45)NMQ9xk%Ur zHz=R`wG&|cy*L!k%b57;^pPNm@#QW?&TAV|oOwkm#$JI|A92x|%eGm?+AT?NsrPog z#7$bcs5kfDqa*QB;8skDL{BG{<_7bUFM4@UsMu};nIAPi7OG6Ywq4}VH&$+ksd1g5 zA75*;4BF&dz#Riw@Y^ay8^NtWzO1Y2#v$>`Yh}7I^3u6#`q?zM!y35f=?5WFc0HDM zPUbkDTD*kamP|@;*%(tNU-+gWBwqt(E?RP8nW+zW2s*cG27JBLwcmn{TVtkZjryEQ z6tyvvWX5|@c;8$P7`#LD{RZUY?>_m3B=Rt=f^^eAt$sZ_MhLvgEP9xR7L^Ev%8x0^ zxTJ=`Bc~2V0e*yU}IrPO03OQ@hbIRx6kWBWIcp8{j7ylnHzV@`S@`e*4np zpBjB)RFForoA(jWIEVNuHLo3(jC@<5M+3Q)QgDvnO>3WaCc;G?-8sRpX+t0c6*Swc5=40~YY4PW8BS9~NLXUp1~PU7K31av zFqit#;{x<*=|O+4B8x;W9QR)p-`Zf=#+9%Zj&0^4JKW?X%TSv_YAcKF~4b2hC{d7CB1ZZU6<&X zqf7!f;|9$c6QfDk<^RNCooXiCYSl|MLy~in>Shjng}$>vwuMjF{b~-lrZB9-MWBcu zx5P(K^mIkPvu(KwHbUd{X;KU%pIXPK3|5Iv6}`G~5DCVAdo5cEvS&J_Xb@)n;e(x( zD-u)6329Vk`E8n%@%%t3<7rZ#>oQ@p!ZmG_t)7Jmece`^n_V8>cz!B-3%_jMJ3*K& z4y5*b5A8#3J9pVLqy;(ez()XQyA&URfeSM%Brj*Z!MB2%tB7Vl>5OQn->h4*vefVo z0E(=5m`_p#a2bKd_UPih`jD20$xXPL=>*b;H~%xUKZ2)erm`sFr}2T+A?Y2zuJQ&a zq-!ergCbectbr?!7c3;&vT?L(LD>#|OQ9f6(`#wE6z)I`I14E}!6Yq?H~XFUj!0Q5 zsr45VRZ7Yng*#ZDi^z0jtj*O9_!;PD&W-J2CEqc7%h+!bSdNM}wATu52NzrBmwZ)e4m_ahSf`5TJYrzD5ncA+-Qal_?g4D*?09-T1UWm0~yT3 zlP5+V;7RQxh*2pYu`8oZS$)au?v?e(1ibabwS^XfZ}=FG{zNdpgZiJ(=M{4~i_ac0Dw--Me`o7X4 zP7eEZyIM5PjE2+7Ak&`X@$Sqfiaku9B=J0U)5*b_+rCnj1wx}&fhqRUDf_-d_&CS zLje+g4R0!iNCMe@!au6}Lf*XiY4#W6H3WT6e}mY=_KX{Qh8_oCv7o^w5M|yLZA7L< zAU~p;AAM9+3hj@sv=W&86D>z%US@ptXza0rA=C{T`z|MY=Ll>s54*B?zDDzvkGJ(2 zjSR@8H?dnq#T9P&fn=y=2e=Z22Nd0PR1Wy`4*VCYXGNBO z8uBZ)q;tU%<3JJ<*aD1Le1CxRAiUy2qdB{`qF!e__J-Dc8NF+BP66v|$@HYcx%|@Q zMT4~#AYR8;``86xd|ZdP8*J-)ps>v+EBlQJF z6Z=tFG)b=oH}`6?LU@O^1!@Hs&{~ofc^lC5afPG319By@<1&_-dQl&RmULZ|zPclm zs?X1qU9>cwT69Ha63b-0t%D#IK|z9&Ne2(!OH7Lqi}?&W@S`7=MfliTd-~Da>}z)C z7hsv82;pO~nRe#tnSCdc!}bKLA{G|ZWGVe?EqfpeKiwZBhI#Ge$TnCU3A2uHfYBla zxv|+Uia#^G#8o;;Qw3G-+N;f_&eKk}D(x;`jZEB8v4t|uixy4zcgE#mWoH`YYvbR5 zqrB%E4d_V7WDlC#JNmFoiic-sP%`rO~zlV4V#tEP))fN@2px0o94iFgcth=)s zEre0Hi>Tdh*RrzvR{)?&!;2)xA$6y3Mk-ce%n|Y^Agm?jP#D_`@t}>uUsFh7Kp*bx z)7OnS+`1WXd%L<(00sw&iGS`?2~Jddwtza}KOHxvCB8G3z#fPqTp_jFL9G2|tLJh3 z`#Q>NHoULNu5D>1^qs}Wn#YIz4vmE>mm5k_0FvwGGS&>TWP?8t?I3k_MWcns738>% zdIFC|UV;sft#2}?Dj zN-~d0HWrz3L&hqG1vf=4Y1F>as!57L;l9u-1PYt44#d-Hphff}96XjIr@WA65o07DptMWPBqjXEV(fPvX%68 zVroW2ovZi~l*9Z4(+j7gTzLs{h?)BGtz@Q!toxO zrZ~oEgCV|BNOd#W;dA3T%azX#z_q8W&fa)C}fv<-4z(l1CTBfU{M$$6%lUPAKgVQke# zdm(#y3YN{$xtz<>6pkZGGwsOh*3&xD0o!S5@RG+DX+2LBkbDFKaMAF1^gAdp9;X$vUCLqjM0*?hH}TCebcj+fG4 z_08s1cMzXizOKgNqD;os!m6EYz(@Pr_{F1OHj8Xu#alIq<%)iP`YE>6@uGTa-J%3> z^Z`-N^TY@KUBZT0c+*tF<4+_Y5+fJOcg~i8vc^*j6@) z8|(#}-XwT#9C3|Ifg!)ruPbH8pCkWY3l_XDct=S2Fb5dNxxwQ$4IpP#Z7vyD$hr4! z12Cf>;&xOP53dh@ky`vC0qNec_}T>U$O-aj(6OtdFhMz$Gr?A92J>_f^Az#t4=iSC zx=RdWaG$2Lv+H)+g5bh7Wa)O?WQLqy!tbF)fH`*mF)HB}&GH2#zxB7nf7kb?g7eO< z4ATf8Nx>do%_4g?YV@*rYLfs|X|}yFkWiJ{!!C6fglGSPC%fG!RR~m$6ThHIGCt{3s ztm8QfXsH}Nxnx98Hb{XGq=>N+{CM^f52vz|1zK8%jZdkT{yr!%V2;E8dUn4=kchGi zySD^??JO+Ey0=|7Um`CKARYh!1Wx`8*ZLqI2uUoc>93CD|VCt-HpyUegY z-**5@%5~cOO}?n6M|XpqU81xD|5!m>$pNo&zRg_zQre6IP~X4whV7YsCZKGGHbR*p zRkFD{EL7!$1#Pmv3AE@tQ0w&%51ghd3%e+(MtQUZtx|uJ?kYNDk+zJO`#?q<3=giV z7fYpG_PK^!_GaoD*I_y0WHkkK=Ii+(t8E-9ESZj4uDzpxSVhKqFO; zH4FbNP=MQh_z2ELH=0i>itl#3w)(K2w*YUxAZXXD29TLX#>o$%NMA!LE@r3M2xTS3qk{nI{q&!DXw?S#_x; zQvX>mp;6o8Uw9)ri>7h8r#%f~j!{$4Q`R?)?iQ1=wFDzqD2@&eQPku>CmB~lK|*}{ zXqa%TGSR0i7|9r5so1+TxG6bq^zH1;*RQg}WOC;~VvJTM`cjgAMjbbI?y>hEk1H`F z3~Lr|*Mt!j&QaEG>WH%2IY$(3bc!FZ3W1XH&@73cdv^3TtPQB!^0kSkjMvKmA&Qf{ zkZrm*JZHNtgQN^aJ^+Y$(Agmu)X5y#oAS4*HR5Qr>k`K6tFP~Eqpx^6_tbLiQZ$)> zq$`oW%?x*EQkM}gvC82$sB&^TTAtVmAyI@D063>#X(4!XlGdxSqjTwIzQweR znR=|RAt}+4F|;FN1B`T-XGjJNDA=y+GD)oW{hAtB0rCip@7GI_T z`D(oV&;*QFOLO?I@0!#oCKG%{0QPw&b44xyh0Lv;+GPD{qy59OG9ON$8``k8JYiZ45oJ-9T)xXikgNq5rz`cw_8 z^*oAx9_9uD04|sUQe>Z+>mk*17^)hq%PLH0wxG1qU6w5S{y64zsAwObS{>JQNk-D{ z*7E5LW`6t_#Sg?puTmsJl*Rx>3n2C&hsLrpL9lQ^DU63bGCA9_O40IMaJTa5{uVTY zB;q@iWm$t(C6mEGW9KeKXNgE(CZ{unlj_J^Drd2ov1&qe>D)x>_wNSdEhzF8*@>>w zt51Rdi#K;;j8A6_khuMAQkl;kaPadOcGajg6aQQ#3*D%HI*g8NNb)E#N?CTULcqpN zjSaK6puJhFEB{Y2TkZj*t(zikPL&5XJZ*siw?P$!rm!Z_sI(ftroiD+E2t3m%D7q2 z>#$9VQN3N^NFd#$hfBCvU(2P@}FCm?t(*zq`=nv!3 zU2K+%N-zVNB-Ca7ATbw(n&g0JIZEb!;eK9hmHR8g+WpphD*yFc*7fscgZ_7AdSz&O z2j?PU$Ngz+IAE_HLH`HgVF!xiv(&BX;~mFZmQIa+pieX24Qp1-&Q50+iRRmA8-UpH zMokFf%^HCpsgDKz{+HU=-lLYh_v6BWr$v6*)5Q^U_Rs|<5D9I`gV)l1rLyqo!w-b` zgQLXR2HTa!#DNcNXJaCS6%)r zOjM5lIHvC=Btr?C5;#adi)R=V$lE^hYKTc$C9bnZ5et3@Zw#_ETCyzLwr$(CZrR2y+qP}nwq140HgDNBr`~JL>+Xq|i1Y94ohQHj zMdZ$txpFPR-L6y@i3T`YvRlNJ8(s_$0_U3_T?=SU!TeVh*oX>86*DzAUjgafZ7+}< zS#9qr<+>H`ZVHI0Rz|}YZM}kt!5LaVSeazRUljTq$xcp+ac^3-Q}}prf0DMw=n3KO zI7TJd7jgWy>f=1uv5)`-1Nyed!L>C%?6m*~3^D~o4u~-!UFlBCsGzG6g{#-Tr?|OY zz21_~tQT@w6QU-WlvzN^x|bJ-;cEH-2~&J1YVIVr6a=_cN++ z$C5KW2Aa-(YL<`fzU?m;FSD#kPvAG|lPDO$fUhJni(IJ{P{Y$p6kISIvTdmn&4XV< z=A2Q5V6PzL0C^z^AUDIV8znGJFuWSGVdjYxb}A`cOHMQW6gR`O_Wo+MG$YvwKQ8)_ z9&_I8gl-h=b|Hf#X+4HL9sGjaCb{*+=`4e{F~=^ZK2AK*F>t9p5f*_nE-#ia#eYQw z*1u718drp50`y-Km(m4MJx|J#k*72DvuGX>)4oJQOvWXffG_lZ1a@7645rY)klbWc*(HY`tEu z%%4Fpb7(i}QO`|(o6Y8i(A_8uz9w`CD!kAG(3G?cDdfu0=jW>*4=m8S|3F`$a?dk@ zofyd_7YZv6nEdiKXI!sldhOE`^pR76@#jtyq>KgQaXf0ep6-e+6 zP3W=976f=2t@Ghf07S(hV1q%e`zWUzhgxQyJhdrdt6H14Z_Q}oihZb}8HHz3gZRTP zW=OL@;uj3UD?QPNPf*I8?6{ z2^bmI`va*hako&vPzyt4KU3k(UZU4+w%Xw<{5Hc!zL`hhNf@AMyvJl>;j6po^wx_A zdCWHJ4UaAr7n~mDEXDkraiK0C2;sccgD1wgj`F7!{l`m0-nsfPN)ANja(sdM)^ADA zv4VCf@!DnG)vG#G$RgsxyJ`n*9rPhHZ8Eym#Fg~y(QX(ai2&Yur>~tB8t9Wb(?ZK; ze#ij+L0}>YSj0`NNuA3FTA(ma`&fU!jmH_Wa(8>f`ASwmulzf;4(x2Yd+E?Po${s=Yk=Fpf^zoYD7je&_!(bg& z#T`$oZgZ22U6N>GMBPQdi-GuRY8@lvixH%hkJ)^z;!|BMdSl~(5iR|b(?}t!*T-em- zuwS)`RKbo3z|?kf(SZZ61>?HLJJ78rqy`dDxaJfb?o7c}rd%|!U{EtlnM_wdCWL#V zv^%+!PeZ;6th5F-{7DY&G{~(yBLAfN1gnLI|ACJQ)F_|dF&-Y0Zx8`Sg{ZVV$K9qN z5bU=;FA`>*rAgl}`fchwKHfBK@Ch_g5ovtzk2Cph8BuBXQT1|50T&|s+JhKjf(ws9 zQ01o%4*R*kf3u;Ur|7DX0O8RJnWS;(h2lmfgI=P0&g9E-1($Q&$p@l*9&L^l&lvK* zhOd~7q@_vbQ@9T~=a90(du?~bL}z??@uu=X&7M#bpuBBfZ-+~_K>?BIt7ODN9p@|& zc|9Uj8MesjAbeA`i1=a$wyOZvvwTN9q!Xvc*bMn5sOgHIS)bqChJ`Lp!42De=CV%R z6UwAEita4Uc<@ImxGFZZI$sE<|KKoVFn9^4UZbfF((9oSPRuicx+ zRvugSjLL5IzEb^2-wt3ZhkyBl(hvH{F(?c3tF6&Xae<2YG2Ru{HOhOUVfAl8>ini_Jp6tc^=`V4wat+E;^t1sQ?uy6w)Id^KvKqE7b#@VDF0n#BU;hcihCQ-=pWf zMFO=%LFqRpaCG$0Q^_~+s}Q&lboV2l96@)r5A6{*`iTd^`%}Z;kh_(T(tsNAdre!r zuiU3gLXuy9Io7iDOj=e=&+7*OnNODa-U!YH;_uOWW+l-y0CTMbjJVTqY8ik?M6;mM zxFl8deXT3gNi4ZZnybm{zrVmYI5!RD)5`XDdCes_Ss6=zUX4Q}4Pc!dX0UIIb3~-M z7eW$lO3!Cv;A9%~z+vP0rt(!id%Yin;Ug$2R>iE(xy&uDW z9D@Fuz0PTxVA-jhib-*YRT3Trrcb_i$7AU%R0UgClLws3k{3!rE`})%p4!E;u?`~U z3xr&=Fx6DtjmJL>_^|dp`dfypYz91Eqz0qFsSmbC-La1M7Jmr=6k4EvOtBFpyY z4w;mMD)aKriwrK!LSJw-rvJhRjTwod z?Mic&dk&AJAvS0tKw*>6`}5wEoXL~QVnuB~nRRcISxMZVtTJLy+Y_G9Sw@@hLkAUN zUVbXQgbPq_>_27*UY-(|Y`XjNgLHto&Huu*!yGG)kJbyVX~e}erL5bo_4|v};NGWx z7ah8dXX78-JbHk+t^cTmfdBrgudSnPvgwUlX9yoa^V4q8dUtu-2v#qz{VVGuFzc60 z?&Sn#8o7-XD$B-ggBhJ^*mls>`vX>0HBURDhLtA$yYX8tKNnMs9m`igM1GkkURVgp z9smF}NiehPUy3LINGRHuegadZ0Z(1v1?=}E(<|Ux{`fS05!gmqu$=S zgtH^a{iA(jA!l4>S4nH~ufw`_6f1Q`yJJ|!57(o-`JrB&l7QUp>vY_GRWbLGtJDIX zReoO#Sp;yV-%n0=%?KhK9oCw!@`llxJ=8tU8<32Ms0oX~80d>55+K%`j7<;%i5TlU zerRVd!Nb`fb=S4Yf6tuaGh$bF{(;(41_u(k6X78ZGNdYc8c#48waUo}Z!G5w zFW+8;nKF+Ja`8daxUeZLTQeZ*bN8+Z8PKWM-3h4uqYQx}p+fJGLk8EzxT`cox+Uix zH~(}o*{g8gtfrJqDf}yczm?2^?RoX`gn?a7F6LIJWHp29WL#!0Q%bH7C;%z9rSL9^ zW!fbZB5mdPbBJAmEsb)fl$61NZ;vFlZU}G`qma@a zVFcX#4-#nkClnyDkt-xyy$W6>=-a1O)Wbp7wF7o}&I#k^8><&`G6 zyW26jQS@%r(Z&FLd;Z9)0~2+f2{;4&>vCNQr4edTNQ*R$_lxQc{dm))xY$zHdbd5e zzOj#_Xul0eUsh&X)~2Wd6c2RhZ;dDU$Nx(3OI#uyuX4JIPRp#_L|(Bc&^xYzIyw_= zm2_p>>P4htCWow8K&}}@_O-+IR?_7;c9O>*^UpEzrDv*~QT6Y-V$}l0rNE<-k??^k z6|9|Vr&1277488&Dh?d??!XxEP#c~_>4#r&61Q{n^Vpt2o%iq%hMN^ zeM>#ZM%j%U3A45mZjw~xPW(iL0dYO+IGPF`6k&k)5$!!q<;!@Jucr;tajH667#}-Y zF6BCJL`{kuHOgNG?Q(I_Hy5#n=|!tNj79G=L-0E%@pPeITLFA9w=ZZKmizJg z4;fB+=<;w1HJh)aZC+c*W}lX!)gKD%0*p<~TY}F#?=xp7auRXjm5hr#)XW$`Y+W^} z(?ngRdqLucM!{8TXpgN&&18c=BbC4f8Ugt6T^>r=(iR>5#=APjJoG!7K3^6UW8fy2 zckdK|Mpj)p9R~5J_&UXa_&Xp7s9>mu$<-I z+G0rD;9%<`!oD(4X|d&WiS~vc9$3XQLh`H0Smq@3iD{qkwG5)PN=h3m_0W}7Z40xv zA4O*r1E;WYme6gta9NEo(h5;gQ?Ys&tQ%i`ID=6@K?p!nQ}@GXT>z z!uz@oME5Jn{6(X)$)&J)+J&b$p*pkQJ&Q-z-#1r{2rY-unum3;oqQ-(M)D3p4~X-s z2nT(!8TFD^Ea-2NVCZvN>?#dFd%FhvsX|?hos;SP35Sz-ltQV&yEHBe(>zqdvLq)# z@rQ@gv|dmCumi)Aj=GY=fC>d!eMLCOCh{U$8|)<2I0WQ#3H?=Hmw#8$%6)_Ek@W#k zRL+}WV7pT>mld5p9yefpM3p#}S(Y1MuH*?Zi6l6H2hUE6guMe2R2J7Pays~8qA8iT z`QN<|a299x5mA8iAthVI?K4jUW@k82TteHbws6=kb1^uq3>ub?GGv0bVfYbiLYjP; zq?5ifg{Y~$|9oEYM7F8(gSH^FF}brE@oax8V;%#w!MY4?P9$a;fQEa-Jz^@X$n1*y zxQ@W}!_|cC5$)hvrtWM3<9vv%|8DQjCFSm-@eQW!W)?Rb4SJz-N+)kf@oRAbXvF{f z&P%21%DdbRgEWLlM)BE>IfW+?4OgPx{#Vwf2mH`#tO41>6&d7O@kTmMni@Wzvt%}s zcg`i@VeiXRW3_07>!`y)X!j4xa$eK;*?oKAeRIRgT-ol_qq7^{+qs9+mo&ixt9eqw zys9uu6WIl_M~#r`@_LnZ%IjVGGXXkr!3*`~VkNh%vr&P(gJE!oju*lCgyZwPn}tIW zVE$=pJlPUo7OE|ML-!#4MV*`>80=BH$R#P`$u*_I%2B#z>?5!;_-wd!Y)W)>F(8x8 zbPCM)O6V`z#CxVCQp}%>1()(naVOz@XoW$-ZQ^Xsj%j8Q;JePSlVrhd7hQRcaU=#Yh953`f62*V>rBkV62-|x&j`=JB zi*+Jh4FbQzfji?qQ%AW&;xJ-IG_S!1ur=KM;#lG`y^Rc5U=!ntcB-Vn3`%~{Kc2!k zbIAgI3~%l*UtXqJ1ohd*kB&vNJlL~uI$N;^bsStq5<5eG=SWftPfxWQ8{xS<-i;#P z5RWuI^<&!`Q5&eY17MJOD7+^Ls`-Tqj~@7qgo>KgU9)Z4cYS*3yzvND{zGg~*pHu& zYMdQQFxeb0{@sb1ptiL};Zvb_9vSATU=&TxU1&3PBjzYeye3M!LDLC-K9CPdLJ}>q)<*jn> zHEiLel3kih_KUbBaEHb{%60aSWa2<(zlUev{niUrs*N6~lJx#>Au&CWCMk(oJ_Hyh zQb=+NyDw&hR;kY>(h|@$_tAb+w|iN(9Vv>XIjn9GoK3;T`JhQqKQWFDFNnZk2-FEg zcXN*k+>+YLZB}XS(iYC|?Vbn47Ym&A6HTEzKsspwZSc11BHzf)tXe&`s1hwjxR?eR zpHjb=7bVNHbV~qgTy{4l&eWrW-7M8J)ZJH&aZ0nn@>|&HsA(od5?A2FWXiY8EN>pN z?G40@)T2v=h^ijK1P2d&i%sS{<5D|Dzr<+wChTy`yvW38x+`M~ z(%XWx?M3omCn9PemZgu`@I*^ndGEgbvYp`)ZOAUYVb)UQb7SU&2m2;3TVZ}~&yv`i zqvAMgn16$F?w01JXH8iM@(Ri2J7lNk)f|pWizc_LcWVICwFqj3PfRZ&_83XCeZcsp ziOk{7+)$1EK=lj@=3%l^9a8Dq-??9^ZV{jYigBq;*3SKny1WC;BKc6IjO!Uw0)T(P z5yow8R!`}Aq_%%oh2(~Q)IFPlBUf>+@oJ*FtQU`P$*`2gyfFS`NE>8jOfZ3!DI#*u z#;qHAeEu9A)XVew-NptjHbM~sFjqJM9v(96!excK50Bk`cU1?dFsm38zz8Y2;C0?8 zT6r}nJYt9#-=B+-ePxuk6r5fA^_>7=# ze1IVHT9|hG<8}xnYSJVb{U5^w!a+Quj#6p3v2nA&nf8j81Z-MEC=+M7RlBJ^9r9pV zs8dF@^DJ4&E94k^ynlwTsDN1(0_vC8(ivY)`Qe%=|CVH|X{l&}RmPeQbp4=1vy3u~ z01kP;`5>?D8BM8f8aLHFSHHR-HSt&aJfO0fALnN?!Ovfuiksep2H8t8*ctQ}B#>8e zE3|)W>RYAQt!uEroeBDYQl}^X+Gov!Mq%1T-=AzDJ$DFO8VYMuw0^zukK;PMNr_`u z%}yzp>}-kh2^ zNM24U?&ud-k5?xW+mNNpDJ;N+#d01+R=O-AR3QzhTBEWlMkznpbWT)Laeu#ZG=Jur zwcF|31*V=1;Hp2GWOyxZVBg=+T{**9PSOtZ)zL_9Vw5cm26R4Y;QW}`M%- zeQ+EsQDs$v0*m6MNZi$4bh}@AMZlk$sm9KC7-%c3r)$sV8X=+t2_ zWD&>|>|9li_hd6yztn9E(j3u@u9@#@uR84cpo+x}?K{GAYamhTg6#ZSzH)_uI6XLb zjz5w_D-3XH^SB|mR3f*-XABtEO6-=x;hg^Hzp2=OK*B<6UP2bGpEp2vQ=i1VjCvel zG3^ku_y%}096qzteaWGJv`)O3UtPtWb+t%d7|=}I$1r5s-cL=M%+A=P{`$~#UZg&u zsyc4d=AtE&jd5HvR4MV>WX-7**A50>=%dBcFbo=q6NgZV6|T7Be;oANNKW@|j*namlBG*9MztUpG%mqj%+VJ78uaxDfm`vaOuhZF=Mt(RH{kf&g+-g)k?x&2^!_nhp+Ma`7 zo-<|RSr$~KL^>u>j;U0toxZYv3%VT)pG;-!-G$fP6$K7B5~p*t?CQjSrOBPp8t`o= z%J^xaA68z%)GuhHY8OX-2#9>7>;-mB8D`s;<5I$;FlS$-(xqJ5%ZPJ+N?aV(vRbu7 z5&&5Q#;;iF$tz)%8fwce41mpf=vZYX0K*Gwz>n#3I^zUoZNz@xu3$zJECZVBaYXIGflb# zt%VNnx$`tiw&(-y<*j;_FMxG35Pp|wV_m#2M?xJ4van`Tf9qOeq6J_6jStt;fz>Y6 zHV0I^pN?iD!MZ!8cF` zwa%Hyhd};wC81cf^=f%kN{nJPLLvRlpkj=L>rzUklhOrn*w04)VFAaO@Gwo*mF;3j z;Xw>WN;3T2_6F8~?1fO#y<}qtGo^&Thf|erCp?&StbwO6fCxhhzHF2&XyZ6klQ$+k zb}{;z(PkXf7_42ulN8Ov?HGksjoNEbi=jL1URX5{({qK@;mcfW0Z@x7V?iYYza12D z{~CAOj~F%al+P_q(T1*|R&BZ&5sp}{k?mrt=c8k)(io(?gLzw#c0Y~ukhRmU0B`kG zud!9yA@~qzald=n>|SXT%~K!JtHcVU9Vu`C+#>l`fetX1K@X|N6XjH!s~$B|+u-^n zH2gtYiG`XnRV7epafFh%^mc|Xf_=|?d8p+~I=x=gy&7}!DnLb|(ANPaQ-v)0mfMzA z(0WW^YiP8gtXg(G9*zZ%Ed__uwb*Q7;L#RhU>i5MJHK8X1t5oY7;x6FK>VObgUpfp zc}64H=z;z7h5yDaNpN?F6IK|HWJ}t&YpGcGR!|CDE`z9@>QL!>e~)<6KQ;uT@` z6D7LPLS)rq^G7V002NuLD{u9LfNFPWz-5GGL=`NboW;sA3QHawpAEZz@8E-uDx0uCI47WPrxGIvMj^r3w~bci9A zAD)JXz)D+}tVvQ*TH;!ML(Rzk-7nG1QF^92+$k72W7K;*7x1JD4@pOSQBU98dS}H~ zsXruFSjvzwxs~F7i#dIbd1M;!VSZ&tZesE%*gh-J^qNr&uog+A9peKeLVX@sUDo3O zo*tlF&o#+slI)ato!4)8pRpmaoNUIHT=V;|GE(LR@92$m{OhV0M<3*C zF*c)-}bW}`Ma!qBJMU`Y*KpGHqy`PtP)kDv)>&(X`md>I1 zv8^g}BZ+&aRnAA_N*@OMaK~nFbg4#QPbcwJp54n#q8a{Aj5M=4P}8#MTe?jac}6f` zREkDvWsI!6O4aTNZ?W70kMOzS`BE#NGp`-X857g{jVS6Vn7C}voT(|6mdvB1-^75y z6l&XHk>(&O(V?Jt1d4!c0AVD`b<@Z zd-{Po(#n2~jcywB3-&#M?_R=zt6_pWCscuYcWO3FVop9OTNP>7#eMZ$CK0fCfwXxG zzXcGFJvcQkCOp%Pj-S$RykPG7zgMRL*Ms8iBq91&d|nMXg9ccwxXi);K(d z`f?3omAQ0!9Gf>WKiRa`MHQQ%ZZ4B4%bkKzi>gtR*iiZJW!b`8lUxX-Qk2qnC322n z)HD7#r45+-`adez7{PHy;Id3Wf7vlGlmTzB;eqAW{l;oG%N4!wZ`^N* zmT%~iHfV71c7AzZ6{IktFFop$iGA0o&l2Lp|UcK zq>~|Mk*9T&j3!-E(k{s)bZDaQ1Qdk$_qeTO;h2wiAe6xGn+kx(3Gy4VPIZGdtuKI? zZ~$A=`Q)D>ItY(o=I*~%xS{PZZ-f!mY4XU+<&aD|DaS=nxJC+@d}ubhsYR0(KMXi8 zosM-ofgNW{j^B2_KOjCCF|Z*zi#C%ZG;R+0TDXTvFcP6mWvg}X9qVQW-MNo_S8!esi0Uldw1XusyyQpOr77-&X%@Pi?_2U8h<5i#Z%uH9D){DFaiaY=s32Z_tWy4IzhcA7xD}Nqwvk(3Q33);UhHm4j2n8h}daaTI0(3ZoVp@u0% zakG;yqRjZ;XFgGr*M1q{*G()_yvF$#s!KJvp&>~J zDHK~y>vehz+B=oAFbrIt><7nXvn`P1IqMa|D9vj|ryOIU3h}5h*9nDwQCM9$x9>oq z1xG2C;P2q~?mP-KgU;QptowyRB*~K&CAM0Je;{cZ>J_7c1S(`&F^B>c-3IC{v|0{}bWMD+;56pS z@V`;}k{vgAB5Le|hu;b5L?K6=&W+suJ31XgSzfPMTnBLU8< zOVp~=h>^b>Wa!pAI!$154%KXkSeYiCs<6!>?So$(Uoj-G&@_`=qBTFB9CmIG8obQm z{B>(9hs!nsqr&t)KMkHjGMqWVKsuLr86$42%|?^Hl+9wBtx(dmS8v)-FAYSezCn-VnAne9_hF5 z7EE2ffv0*ZnG#^#W!1((5v5X%DixV1`4t)x>Y=nFc-q+vPr((3C>R@u)t(y~Wad96 zZ+RMLEsH`>-mHd2sYzDE01CR!inSLndW9lxGQi$2Y@}zZPKV>S(xN>%r}Su}!7hTu zX1)xqfG**;K5I-q!mPoto^-!9BS_p#oXnm{`c{m2@P-qvy>w!;QfEgT4ni1vA3b#F zp5=)Y(!qKZcSeL%TI&Bx!LVS(_1enLO1C_DQ3Z-EzFR}+&Yb;T(*}rUpLlSbT=%m! zxLho-d!=SC!mn^L)#Zwg;=-3`@I@@M6Gw;xcN}ZYDOEk&2V4AXq|Tg6(0=fw#jK`I zSKO0l1R=K*gNFs1KB~6S5uzB`x#(O6z)6KGASv%pT(A2c&9hpZnA#iS?N3mW7R zZ;^OW7=0-Ii^psG7#4@K)c|HC(Ks;~RsMM{1||`q0dqx2V=Jr?t;&R>{`dt52ij)k zh1D)KvO>1+#~dGE4)6bnp=iCrh?`U!02-$9R?OJZEV&LkK|F|XrMKyLd(A7Xk%9ei zrGeB%*kJ@e7Dxbd`2RCX{wF@#-|COIB2gmB7u0Mngsb4sx--EHl79_+0KfoY+};B0 z_7mFpVnT&X0tobA+xnTTJ*lxnq;tAXg(UQEFn}1Yz~)_`cK7`r2J}~7)4K`iqpS3S z%Vmbo@|%g|{#H%0^euE(?B0&?5gchAm}aQmmOvD>2_tVeizMT)TF}^~C@ULV(CnR! zpODg^q$$w5y}Ta?N`cDXmhKLfs4$OPr=CUDugWZLlAPEetp{JjSVUV#R=1ifChty7 zyVX@ZYf%Z+2T#g7ebMyy=$Na7p|DL{CiIS(C@4Y1V70$r^D~@wq4SsP7|W?rdgA>U z^?#n0RWL{B|M{9AEVMu@^FO{uD=B_TW^6I{Gyp;plEaYhKO3n4a}56H3mL4(zKS;j zpK|$*Wf#1%2Ee_4fe!mw{d4$6{~w1BVIr7e{;!7*pG8?OAZV<-y&$k}3REKdCzOA(tF^ z4(VRfemzoQCAlQ0;|XF%h;@z#59&SI{<1CW*ArKV#6oS_#?d;$VXXsUFJ}ZlgM@dj z?*+?{tij0N38voL2k&*DOMV7if2yzHKwIuZmdC819oj2ev-OpkMT2JS4idmCWrB@( zb|jl69y`nY8+xGl#9kNoE=h zBP_5&H7Rpg0h4jP1Yv$#Z|)eeJ)}`UOJm^K>&jmvGp-uix;-Bi9CF)&L)y#wS*?!$ z5Rv!Z-UcYnnG$50#$hGUWl^nGjg(erk zioZ~|C%m6QEuOY>_@YwGxtiFYMep}F{MEg3{daITE-=tv<5qHcMYy{rZ_6iYAE7}o zI$E3*Tzb98Y%$UUFKxpC8Y>@@1dvZ2?OQPP=!_*3ltm=IGA7#NYy%zh$O;Yb^UKs6IjYYmgmrtEI-m|S}Q53eQS?>d*r9-f?>9#kazS} z5b6{6MW+l9x8SEq#+=j0NFNB|9sq25uZnSqUlIOX7z9ZtPU0XsGa5b!V`#Hb@Um_H zc1qqjqe;D;M$Mkfdb8PfHFh1TNTo2NzI%nrfn$~~hAK`aoE6C-+qU&?cpi}M>>jpQ z#E`?_voBiEIn*qKqoG6TCxT=&tueL&wL~|v*Q_K25igOUdc)$c=$Y3ayf8v#gZubO zT!8S451N4n&#i_qyYVF47As;iQQuOF!r}*0cjw>5rJmg3H^6pgZ(fV2ANfmU*YO&N z!(URF^2A-r)}`B_qU7gZWwaG|mj0JZ9V;R1EG2f5n;`<_Gd4|~Y|DoK7zx@rqUQ?` zYVYlDqgNRww|QXd{&~WC9|+<1(J3+NkR$Vx6KS+4(#v|jLMTlbHt?;PRcLWUz%PF^ zgPVE*yoC&2?A2SrFM8Hlp!{4gY2%*ee_9jaTkJ08nZoz+qDm*tT+-r#;a|~#ARxkn?HvL0z&cHvp?)q7l87D z-IH2C0};5acT8_6ews1z9cA;fV`Zqj$_oZ$3cf?QB5owRa+w0zZp+-bn;QDUWKnq^ zWduj~DH9oEI&m&Gc0*|CKqn^yUyNjC`!)!X9e1%;Se#FkgnSl|tcfi81x1xCR5wI6-%N^TOWxioRpp>-I7Ma?~D1!Xv{P!feO}XV!6A zq#NRT?Kyt7M<=RxVY?R!l`)6VaMVqGqFKXcALrITMm&P@}Nifs?tNE@aZ@RzOMH<#rLTcYe7fRJT2q= zS_MwMB@2kV8UT685}fSv@+e2}%A!1F9GO!}|q9Lr;vHLKg5+ocF|*n7J63_p~f&V0_ISQW#y ze0{1BS8L`Zp#~T=55)K1R`p*B1rnWfN<$o4RYniB>5??%r>X}pX6@~@!+%4gj!w1@ zbd0%S6N(2D4^~@wuI=|;(y(2Yni^iUFoCGwWudQUhC(p~(x7#Kw~9MHX5K9>wsOFj zz3wv-a4nC8VGf3+V#1>QI-a3*qga;4efMXkSkw68Id9segr?4PpfBHBNSa{o~%Sgwj6 zs%_t@zKDZ6j!L-n_<&Ki(@jW!Vjy3dt&$gagfpCW^N zTzlS8Lw<8?S0x}VS6);50&l&^_0QE7hB_sT&$)4??h73I9^4_%jxGqK70A?3bag;b zcSwL(I)&OLsL8L0>SE}23!7phq7$!uy?n@$P7I*Ia1qy)aphHX8Tf9a*sm;#)gES% zP>xy;Cg-HinJy@oJs_?YI{0oo2_cLB-M#-+5i1rI!`fY4(Y9=*x6`~8Ps@|EqPhSv zNG86V;WqJ90Knl&&8kKVY;RKg{--Pv`o$cCsgJyEYNm-2!?aK+WhtwQ%=CTu8E#W` zB%AhAx%#w{+tP0GR~0P5flCXP+AA!>~rnyo#N&=7Jg}p}?zYZ_jY_#LCErU?3+8`kZ z^3n?lz?uCmrga-U@MO>j!P0@)oONzCDmR|v$TYzT*I(H|P{^Li@Sv-m^OztQy=ATt zwu|x2%&&k}#G6@s<2DNIy)PnrM52otP*VOkvmplsbJuPmCFS9lhQ}TD=6g*s8w<>HA8jSsv$_eC-FQ0n5s!0PA|v$F5x|`8!3=GTKsP6 zT{RS*#H_*xP1}~J`mR`B3T{jGMl5k`mWXVOFmGOnAKKYmeiYAb4S$~HD_3`6D4XHY z3eC*K`*|bHuK`y5?vVtwjdr-kEb=SrS~*FO%Vz_~$((1rg_uFVM-A?&!~X0})HW^U z8T&zOB~BH^VkF7bFwX4Zc@$B&Z#&HL=HuxVFA1K0Yqoq%SzXr$QSYJvnxs^=7L}XE z;S9YLVkI>2$yAh~Vc;Ga#0X^@kbHcNb8AQ1WipqQwhqu%SSzY9fo^EFzoWCW>(apt zxX*)hmxi(dhHqatMnUGtWIn(Qdt-mf#Jw*PC(=BXvkB-W6Kb^jyeUko+s?@9ah!zYjjE-x;caBm8Ithi9!AN6Kgc$l1pvDD-rX$bhiiH4$3J@TmMBaV z!iu0|WIhJmBZ%C9|7MDFU4@0fuH5O_?l%o{ z5pz#N8#Qof^DI&t)ytPV9x5-`e!luJEDz8{mcbL8EkYZk=`E`$tX>lK)X{RodG$<+ zjK%VafAjMabf7y!0}1ldw+jNzvfvKO7f8Zg5d?zF%mb$_uqels!P7hKKi}B{>J;4n z?T3)edIw}V)GSb}G^8yn7mrk*>t@rFURH8MocJCm>=4NFVcjnt6c3?2zF6rsT#$g3s%P+q26ZD9=#e+pT{n zY=dX`a-jgH72^1|X9jRMpgH&2=yo|PXdtQB`j8hI+vKsV%~-L7afV_ENqr45fs_p) zp=HI}>{;*e=B3iZG3v+P_0Fi@_ z;=O%kil+(Ds%KF$&IE`1(?1k@SsW)sw9@R{<)iPxC8-Vr@R}#_LGsu)3trn!`8r{BGEzdLvuo*@L4?eW%JEt*@>ic%UQbk~}XEmoy`I!53YSLsfoQ8ChoY z%r->Ll2i+wv$TF6BnxbbdUvf@#QqW@BbmbEk0ue!AL*le{!ACn@`Z>!FaF_`Pb|aS zQG5)3o^$?h{X0ixmPB!WLP6h@NC*Qyu3KY}EWp6{21!2C>f~GZthYkrQnvCbLuuar z0U8hZEaHIHOiZi5KfFg6xC_~ty`NwJO?|gRs?@D7A&O>W@UBFvpD2`u;333{nvNfTNow++k}2l zn3e+$+3xQ>*%0veWrXfEm>OGnJT?%X57xB$Cm7=WI#g)_Z%aFzlUeyqoy)}{I*?ks zl%&)6=upzo^=e!h**?EGwxizjE;(lI~UzP%~*H{`6CwrPS%fE zN&qvV$GW5T(*IWPw8JPOwK0;Be3=xjgzIzn%A(%IP!-E|J6c{%!g?o&v3OQPL;J3> zgpLF`9w0)8gdc|cUJ14o8lYRZ8bl{NnSa(&CN+T3?GnjA*zgIlP21vSzy(xi)X(Nm zV(fZ{xP)QSJpzuwLk@>X zkxt%}{m}QHu3k0M-2KvpJ!a>B{3P@IHY_Lj6H#es@%b7A%^Qo0mM`PtP26zqIz%N# z3Qg>(BOCOtbT2A*bbRJS&08>rts(BLFtt*i5mW4S0_O;bFmcV=ky)k)!D_!D z0Vit3Tq5Sms{*PV2h?jCnMC^l0&_P3gQn+5$L`cuN#B*79H6|vZmzsERS*D^i6}@5 zWax$6Sv2R$5#r6%14Dy)Yr0(x6gNS*@|&_>g`fMR`_`|SO=07OE#Yr9xsUoKb(S}; z4z2;q7byrC^My23HmZ3t9-vp0#(Gp3c@vYF$_glmeUT9OdXvm8OAYL(sdJ(8GA)MG+~?uDk7^XHJ1;V{DR|3V)MXxmpZrGk zpR&IHOv3&_=%CQ3Dq}X{y+kj|PzM-wzyE=bU3lcj?5hJu+gsv9VE#7MelbYThBpkt zlMLX=lDV2ky}MHLE@ro=#&29*tUG8-^Tgyu`;YWa_TS}s;g&v)^z@A~+;r+f9UL7x z+Q6~R*TO6r*ZAr~>qH{Igf7c@50df`>M~Jvl5gOrFQifLa1bnnDD)+xmcu1Y%mBr> zXaar=(*C;~FOV0#Q{;cI9-=~Gaic8|Ae>TM}ppP*iWHEmXTv6Iq!k^3t2yvn(8)>mGOv&+Uz`@z}tYBv(#Q`@Xx%DoJ) zH3mZ?bPZLzjjf(rwRr@89%@CSRT<_5N7Ec=og2cRewRh%N@X<0)+tF5uvKM&q7DCRs{ z;YpmOmEBs^aEtx1p%#qcDKD{j{D$pj?gC@WnHieoMkL}SeAdXQ9+YiUVFzLZ&g>xU zd@@O1mu^?kbOsAOx_bf@s>Z`zxnP3k-Byf%*Pge)VZZ(@pWLtl23!xaBz~LQib$zk z*8*>?plK{ofxSGaMEc6z-$UDdgTygwX{J915}*3isaD4~^s;W}#CF65uU^fADxcQO zK}ntKK~i=>0TPLp(Gv$(v7Okoaw{ zmQjK#qoe!Ug1e7=5GxR~dl7BO@YdI*7?85IO7*;#3f&zT+MdnCVjef3ZrKXMTY)gh5;0#F)>^fK-UQB6P^cDKD|X^r;*0wXJVxy}a+| zdh`@^T8+igXXsIksPv*P&m`qSkKyM{v88i`f~E|QywFvo)u;6}iW0KxIIH5Cvu|-V ze6t7kObkBs}kmqyoulf0*Dl zvXqzv!IIJ?b}0bk-j?5g-lB-VB=T`BZ`^J@givQvO55!~&DthQftjLM%D5vOqoYEs zFZ!#p{f;H5hb~>XiU>2JC55B1XPFE7)W;XnZ(2Z>&K0MnwKIhIM&w~oO;9jY=vw`C z=uy%OTO3CZyX8FNj+48sBa`&9^M$^}w+n1O_^xCh;(CM?@)x zC?VOQuUYkg%!Nk@Mq^huyPKs5j@Sl22f-h9wuTYjlZGhE8u?>1_^UFg!< z$rQaA@Md(jjzPqv?3XlNrro=Iuy;~bxi2^|M=ay!nv|kKs!~JdykENI675(TGE^9CNG0;#W`A`R9Wt8C~LQ0WM zEN7ZlV6bnN6Ub{jx z3Hphld_o17nv_yBwc@$goG=M(9DrSqhnNxHa*g|Kmx?KXX*;J=Gj&W(folWfhpGb# zv{(ilp^Q0KD4g9VsUsWI>|@3LsVcM35HJ!^n1fPumw zQ3U?*XUL+@{?imS?{Y8fX)R6T@b1Bsqj)OMbXokVTO2#YzdylS;=j1t|Krd8KYLNP z+fQ9;U?J!T$OYW2w+ONRTI?Ernj7RaDVVWDRQ)7t6=Kj9xB$nyo_2g<(Sq4?|GWtP zjkp}hbJgje!tehWN5f>TjaK6=cB~t?WJ?~V!?rPl+Jz^chJF3n!1{l4Y5&|DYEnSV zCM)zH1WoLUa)?v~hd0W}hN@X|eebsMOY^9XJAEbaC3HUfb(Xem~zc z{udq6zdY4HJ8TdZ>Of{&R2~BNy;}W|04flteqgjeo5=p1&gfse-8WouNU)wwe>)Z|7&6o;rpwZ%J0WbK*n)g6F&+*ZTdOWMpm0Aw}ACBot#k* zEujHwjhToQ{R~Wl!GgamcZ*?M7DxUgjMJiTGI{N%>yF_mH{j(IfpdCq@)(r(LK{= z_MXx3+edDK%|G;0zlEcNtlkoJYo3mzc}z;e9H`LR)6EVz{g{VHX4bPj}ZI7jqWH?@ZGu5xrBBicld%4=u32qpZiEwwBDEJ5vm` z*uQ*s&*$@IhS8tMME>Iat-W$ch6qP*t>J&Jd^25MR&4t z&uUCc-@O5O?yV24x6k?GN*hD9*4V+4#ENS?SE(*NVkT>rvO9l#Lbf1iP?{$-Z2c)s zCtat;AtA){YFt)}r2icF)kA&4SiNh9Qo4Ly3d(X8a18muA*uLrha+Fiwh z6S|!<9?5*8ZAM({nBn#m1!fQ&k{_ULUtO6nDyLR3@_ATVjQC}X*2xQ+zvT_>uNmSW z7^9jw`me&GQoV~NIJ32 zmAYZeu&7bnpUkXIh%b_k$ga7R?j7#qd6AuP+b?$Vh5Pa1#u=6^nrZ!Sz9>)6$uA8X zR2LKH_Nq|it7_DkGUx2H=;+d$!R#q#41UZL2rY*Xrv7SaA6tEbGi^f|laeQ1GJ4!b z>FQ{sur2Ed%?1|j34++{pgCUoe@)j-B^tC76Gc=0l=-bRXuY>BKs{YkA}i`lPO0cx zx-rJ%a9#W=`&*7@7;7Ie*XfuDOvLQYStc{B#~iv7 z=XWVoGB-GOot?C4^)c!Xg-l%SCPMasu)Odb_-Dqt^ zvF`Nu&8nx|3e5bWWr&7d=3@;>`LYRxZ6UW4rh66FFQgxRB4oRD-ScuE^J>TCq|i;3 zm0NSky!%`9o)t_ro=|JN^m^;_(>#wM0YN^63oi~%U#`xYWVYv6@iZ>OVEI^u|I>9oyy!>@3)W7f@P25Zw#=ae*w5(frdi;2!U616-!GwnDj z(RR^2_o7LD@zsLj({%=E=PBNP501|42z_ATYf&j!%x}uRU$Y~5WbxTm$%kn0ew@|{ zZ!6cNf=Ql%bPvylz%uTp&LmgoBA3#6HP`oL>tC#Pj$d@X%22zl^eUUF_VT_L%XYuT zSpMCiRhztmi*8Rnpv5ZnuQjVly>Ki?uyejX zY=~aSJ{|?}$fI`!+Pk_3h{{sySof2Tskay>Q@?L*Ky_}}QgcZ*DfiURuFH&0%-%Ij zVqREQ;i8Cvz01b>4Am2r3&485oa`EuJ0R}O_>#PV_X_ujR&6x&D<@Zo-8FU@ckH*3 zeRs6%P9u(=#_#I9-o`~m1SehwwcW?cIQmL5is;>EvBn3{TLkVuw`gwr z4X`H_s-`Pe`LQa7e@caYRWS6O3O}oQq2EJpM1&BQ!{G{d_;hsK2hp@ zzX6K(lnA*h+xC`;2=&wEM^cxAY6*Y2d`>u*x76(o=KYX9n5VCKi9rZq09nv!d>(KL zox|(#1sQA7v=8@g2{yY>U^RAy#xiM~NVx{H%B41#TYfrx>rmxZER>C;dqgO(F`btBM_zU(eCS_b^+O;L)@*Yr*J zua$&9{HFw!FbRmvY>DC=AJf&*fqm$P@go(dN+cab7zi2i`0^9SdOSUx5;y=`*a&_S zm~cNpWn%a{TYQ?(2Tw)Lb-Q^_8#l3D?hE**^aK8-{ipnWY5o6gKVSMh|I_nR;4X#B zZ-o3#$nR74{UPLmZcVoiGw8QIhmgTQxI5Fp9HJAk6#^q%B#lhyTLrS@j9CdVf~;Bv{~>%0Iv7WcL&&lm#z%qQI_PI2GzRj2KhUY{ zg>gv;jn4u*3BU^a;4+(qfV>AGtsIyG))#KfF-;P7WRT*9yA^RXQ7t@d^aEz07;hQ3LM6x833?HPXNvU><8LvEa3PIv3@eN z4*?Gb1OV({FNwf?6taAr8ORO*YXJ6V22g5~n9%kHVEq(;DL_fzs}1omJOXSm5dgM; zFaeDZXMuvbbU6nRnJZ@<$W)Qkl`A<|(L-ZdiqtmZ2tNWlG@()DgRxWOLlrU{CfYbT J+Su9J{tdLgt=j+q diff --git a/docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 b/docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..b75a7022294482208589f788449f2be728ad11f5 GIT binary patch literal 166391 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 J8xT`j{}*aznw0 Date: Sun, 31 Mar 2024 15:52:07 -0400 Subject: [PATCH 19/93] complete the how to section --- .../src/howto/repeater_grid/grid_sim6x6hv.mp4 | Bin 166391 -> 0 bytes docs/src/howto/repeater_grid/repeater_grid.md | 10 - docs/src/howto/repeatergrid/repeatergrid.md | 205 ++++++++++++++++++ .../repeatergrid.jl} | 0 4 files changed, 205 insertions(+), 10 deletions(-) delete mode 100644 docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 delete mode 100644 docs/src/howto/repeater_grid/repeater_grid.md create mode 100644 docs/src/howto/repeatergrid/repeatergrid.md rename examples/{repeater_grid/repeater_grid.jl => repeatergrid/repeatergrid.jl} (100%) diff --git a/docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 b/docs/src/howto/repeater_grid/grid_sim6x6hv.mp4 deleted file mode 100644 index b75a7022294482208589f788449f2be728ad11f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 166391 zcmX_nW0W9Eux4}Gwr$(Crfu7{ZBE;^ZQHhO+r53?+ud`jDkHu?2J%my$^-xaz&CMn zw=;LNwFUqH0{CzIeHry#3>mELm>B>70KiQgjEw<+y!ot+^qqcn^8SGS{A6v4oOKU_}TIt)++B%rh{pXj~%*op7SI5@Q z$=ue)krUrg-$37xhXLQg*o21#-^kd&%GS`5hk=uxlOA8+M&HWa(U^zcjfs=qje&s) z-`beR%-9Xz(b?daV#l|0bpJK|{pvax@i5TR{~G;%@U6|=jE!{v^T_aPq3fV;V`|L9 zz>05Z=3r~BulsAtfbZmBY-MHc$is-w?#6Cp==2L2+FSF`|AwG%#GIRK~aO7d&z_+rswbVEJ<#hia$b|1` zWp4Nz%>M)E@ogObXA(nmYkjBx0x`F7GIp@i|5f_M4Xm6U^xbt0ZLRI}oql=4-x@hN z=$qU8y7*Oe(Em@z#6jQM*pY_`-$2*S{g*a3`pv>XSKmnA?!Pn)bPde)9sire+`;%a zF(!OhV{=n8Cxc&^t(~!ruBolvuk?RGyI)gFWA|U*Jd7;#|CiLYHn-tnpvQMKG`2A| zbavulrvEQY2mSwQ>R{|>_G|87sQdrZ<@vRAFyt|GFu}Jr_$};zY5g)hjKAH$xBo90 z9(r2VU()VB$Nw|xyYaAc`~r?n#&$f+_~v%MUHV-SzfJs|OW*!?0sPla06zc#N+jd3 zAOM7)@0StT-s00YlZh-59s>G^)pv37F15>9MrQy3;Qx6*vrd`|k+H_ZO#Wl3n|!|t z_JPHNfX^f_fY%$Ls?2C|Y+DPrtf_3*j|)+0X@(Vv!kD3zq#j<8@m;;Tlckd-=W!Cb zpmBIqaiO&VKl}s0rKvJabOT{>N(}7}iHaQ-KR!D;?-G*yq+e9WnK{=^qzzE=UB;^YsS;Un@mO4ljeEcQ1gCin6>S{v5$VCVBz|NkO*;wMnXgjisuXp^hwP0u81p075`~9Uy6ev*wQR zUFtf?9RopPw=~e{{Ol&n5TE;vcm1_$H|(pHjyWQ^SQ@_<-?}s#cowtL%YfZjYxQcK z<-57kw7Sx5P>6a7&3_!+=ibSaq6FXXnrLKQ+<*!Jkx=6Z71&daG=M=h;#^`!Emh%% zu<{|3qJ=Ae4O2a&c9*$k9>Hd-3?7NVh*H@>IOzMj!eQ=+$AH$bgNw3MRgFSxTRV-m zpPSpUu!r1+Ls*_zF2iNsH#ih1lZ5uzg{5C>bNTs8>Xgz79bD>pIS#*};rX?kx!2JA zcjjri$6ktJ&?YHiGh5{NJLDzS&a6k$K%QaUQM0F{=p~yrlB8J6)C}+Q23a*G+eAZf z#O>H=+Zwi5-ou28qU zH%Ok9$d2u;GU)Bp?W?!0F_xq9NRfH}4WM4%b)Gr$GG>`GnSgJT*Dy3NF;2wUjEB7f ziIaMlHce!dChKm;b=$HrI$Gp|3bwW9`j)`hKO0IAQ;HY6$5PDeQo(g-R9~VDF-u{(iSPqes0HOw#S(Q9%TV5e-ck*DrysT3E}Swfc=fWxP?XGcdgFPMSA9GS?3w_oFi9AulOWR+A4_WiUP1 z&q{h8T9A`yZmK{i)FV~Fo_X}1V{ubEx;RcP1;_JZk)cvm)$ zgFdCrF{6tj_>X?N72(doAhcM8nenfc!QgkFTW}Fk-u0S^Ku@Ig1 z%ueK8ST5p<{(|*Pisz-f;Yg$gpdw4w5}_&ekMi*-%CBs zp=~HAa~A#xvh9vFIJ3^Ljqf;*v!aOh?CgXv)VcKa(Gsv!E{ z0ChdEOzj$KEy(#OC<>MVwlw+cP%MOcf8n932m*25v&iKP4h5hwTZHV&u^7Zs(9rpl z{sp0luBc&16Ra=kumi*8QZd49SUZo(`LO^c$rOLOW+?s=={4A^eQneogzRU?HpP@g zV?#xU<7Hc}?Xev->_2S-o`LkY65I$U>n#$uxV-*GnPeJ_9Db#;m}Um`R9 zc^;pu@ZP&e-^YG=KqOd5IymWVy>}!6qEKGP6YsFI}l z_ILADT|?X5aWV^Kat{QgD0S%()-(p?4B8(ftQ>qJkb_(~p$UOWWARTX)nCZ0jJc_@ z0B&NLgdf&$JicLc@k{Y@%a=f4gcd@#n%y0np)K2&AL&brwL@K)Z&}1Vy)Sf_gJEiL zqc2wMo`*(m1e8QTw4BT}9N!bh$i$#ITB^FsEi3q;5c*Nibhf(kden}@sEwP@pFRi3 zDb>*$vFo`6YavM?>`hD|#A@5K)!+_kuT8s-%CQmRv@M`cwQDu`d*~1j+Hc`dit6pV zA1_5EC;YinnxT`aipGBqUCujs*1mickFA8<P}(&1axV=wU>XHH0D zcviNx9hhdJFv|7n@|&k7MCXC-`nwBXd$^Dj^^z`i;lNVYyD7)J7?KPS?UXIBU%b`3 z#oA-@4w$cUeI37z#@A8VQOdy1G-t#D4z$NSD8{vdt~tC0XpwF&B4or=_7j^~EF$Al zXdejJCRDh5xJpg%0)Nz#tgi5eI%luj`KJhpz1|+g!6RELuhyDGr6z6)9Ma$?H{qPA zka|*%)Hrd9O*DdJ8s`@Xl=~W3-Ve0mX;3_rG8#SesP0CF5Z0NX zW<@%M;MlnGpdD%~vxZ&iEhMAxe+aSh4C>4@o}60>h-%$QHW38yrSht)jhs8hF7>Pe zN{24fXif7kfOno=jkfI)fv(18Pq4Ad63qHvdoE>h*FnUygI`MSM=A2Wy;UbfydD1b z!Br*%XFS%U$#3Hbu z?j!sJG`B461>x;3XIt{cj&TRJ$FZh_QgHrjQSPHU5XMw0nn}P7Mo!;b{-0PUvt_6O z4gbmg>g>N4&R{oJ8`XB#a77Go!H_%47t-y;jZT~9-P7)rIYi*^H|*-xlz8{tq9AxX zf?U512@&YE>_PMml}KLUewnVmH?Zps1PK=&umTQnRUuN?0_7)5c`10g>B+a?)Mhxvac;ebJCuDNOC5Xb~zWOuW~}(hGgAMuumSh}N|< z#MGWyA^{2YaR!$0N4?N2^@8ls^}tT#ms*TtZ({92Wa5qFAWFYZ`-bi})85y^3u^Ig zp-4S05|XdJiD0PwmqkM^I*U!v>3pSqjzD+e)dM(HroHZMCO56|7^y_l{kVFDwkbQ# z0T#4*#^av!4_E4hOiZu{j8Kyq78UZ~oF%E&3`f_}uPPW+G6R?Wa12I^b|b$u$hivk*#P&7%P}uv_CRaF(WKUr?=s*9I)Nn+5(5|}xGBA8q7hv`FUE~@() z4jW!H69V|`9H zhwkw$lZFUq8<=N2^wJ$E14;#2qf@v5T_i^raDv{Vi((hF@;|Z8MyR>dIU)~2T9^pm zkHb-ioEf~B^3Cdcvn$+z0Gcz=Mr;6M@j2*v8wYk zpT*fT43}Xk@Q{>99$pqzc*RgZEU-cUhS8pzk3dn&RKc7>n&c88l-Vn8_Z|Hnmha%l zS_3~P0dPCfh*N%7{YFoRlg~irOqdqLgh0ws`?dgfkfNTV{)?3{3YPwbZ?ubD2n_}D z^~8bNx=S+@G#bW*LDj{6y~6lUq?E|&9+_qOfQmNqEz>t{?qy@_4QbMXajV@a)G)I< zMEEtK{XY8@U}wUWVQ&x4U&*5dQ+NpuRg?ft6}jsC!w-STtMIw|ASkMeN#?GBo`=o@ zTVmi|Q*&>CdDEiAEPEJFbcz(BL-vzIQ(Y1AT(G0jWm=&N;SfD1_5&y4DulKX8cj^c7x|Y7cz+*LU+IPijRrs8g7yeKjc@+(6=K(e$fWp} z_ZndZKjyX?YG#}&dr96j2Bqg|i;cC6#8wXfUdhc+sezq05Ojw51r;bJ*d2XaNw!(g z!m?^;+{Bj7z4AD4wQrByI}3^ihAN!HwoBQrf7T{ihJO`st>!JYYFrK^B`h`AZtI=0 zK*i1I>StwaN<)C`45JRvRyCsdj!~t2!*1?3-Tmg(A~bX68ATMnj=(ZEu`K&89ekPU z!ZkWlRGZOwQ*L1m+W00>Tr!(FMeVXE6Oc2nKuqUYbtg{)N8O?-4LZ}XEw10mMX8CY zCp1Su3T-MxGML%C&7+a6XAG-e+KOI2>ZbX%(RN6BtCgZn`fgBU zRQkzLXr^Fa$8y4>_^ADx(RhP4ulyhtIiF}Z zCEgY#p>uVqk&dyF#LHY>Lo0VJDMzhRbko2#i}3to@Qquib-`(a27WNqL}Y-$Ry-M| zpg;FI*{>=dCt@j;01v&fMWP0PTmxnmi!igOYThajXdU`0UPLYFf9r7ZOpO@s^Nf2S zupAhsOpN*5Pw@b~n~D6?fE3>Y^ekm z#|@vcyBEz=*%zkkC^n}>NftN%lBG};xur^D{X{d#deZqKV@(0usQ^3CN<5m2+6ci* zmSL>Hzj=E!NmPMnO(Rn7)FztDC9Ee@c?n#5=XzL5Kb%s4N-!bQhK0>9t94RU!;FMq|s9`oDGve*JDM|T<6aW#Ylpo%8ReuiqT0D2Lt?b=HA`(;fybJO-Ljv-@3<`5-B z$cb>}r}egm>siiEi>@J55c+73qeubW@0IU5-$j8@Y-j@IfRC|eEA8C7R>jX&8%c_w z)*6pYOS&uC1aY^>kbyV;MVQ-dj%);&D>tB;vWx`0hj*JzPj-gbzn!}JH;sHOihWQY zZmG>o>ji+WP3zcz>J{@@Qmd$bre=nCiK|n>3-A7+t`Sb(Bx0A~4+Kst6dVe~HYT|9 zR(qtKr+Q=NF|Ie3&+FnqJWUZtDfKUEz5&Kb99mIj4`}viNZ$+_djJ2}u%72?tIP2z{0 zRR+GI$lDHSc(t)O@1r_- z<enpKVdFF82@trJf$kNPW1|_xu64*fUE2aiaNOLo@0FmOM?wZQy= z9}+k$+W%8v(9V0rN4yQCoxVU4z~Cu_*YlQ2JQ~b){NSS5B5bQrciz%kW$uOs`v?F0 zk9d)q7rL?%`l?h%zn|fN#1+7~-e+o2mHQ5}E25KkK(A?LbV!h-gq_ z-mPjFmiX}3Pu`+ez_aUshr((3I63MI*SaX9X4_LDhVJhBxxOS_@{13`v+6yzWwuYmpk(Ny@%l`9=B7KwLQ<+`sk#mf9 zB7evjTsR8-=ZxHS2Ni}F*`eH6(r3$IZO9PAaxF9I=WC@qK=r{o5V9miS?q>f$Gp$c zk*R5hwba`AwIV>V%UFxSEi$@^)V-TU4%d)R+B$(O=&hoZl9XHhU#{^W11YyFOqM$D zKM#Yhp+nZoKfACgK}y&{^iw8sqoW}-T)LPAUw?GBY5qj;ckiK=L)++lzk=yt7`@Vl z?>Go(DRqcTDtfuoS-3=sgGLUIQ*>l#CP_8N7luZlJe()~lh10*LhWh-vys4=>+|Vf zdqNBI9<}*P#%6+^-9K%XFeyjT@CRzXrkAVnDC6-P6L#Spa%$|`b1^rBM5KhgrFl>! z>{Mq%ekW;U6f7bZE{$MPyfWex2 zvA;!~fz-h1gh>m@VajrnU`}Qh^ZngQqWidZdd8wlpJ;mKy;bTtMml-bAAGj$uW&@m zbr>)0v`_N}i@CvA&u-$uyc+DkU9F-*HNpt~?Q12Z#dV>+f3AY1r;MMBks5e4I|9s_ z0zf9XsnQ8MZY~mc3t+J{83Ppk8Xr#RK{yF1aWbbl@~J^}A|-ZRBnnf}49Zc9WEQ$l zou14bV*KzYYub?5!0qmXvDv}V8~e}RTJo0QcaAFZnSLxC9q=11mB1!)u?nP5!-xFf ziq04B>}UyyP+}jVEL1;v<%w;S3-ObeNp(TE#sjdBI9D5FBF#WiT-ahAkXs6efaMNQp6Li-nkYTj@f~DkKtJvF3`(T2%WG z*rFlHNoZCU*vX8qT5YhcB+k9cl{YCFyes|KlaBgZ??hD0?7He(0ZUFq-)e~xWVzSf zt|RA;afD-#PrkobrVR=B;_=nk_+r3vwjN1P#mFSO7p%{uX)7o3|b z`=}d#>Qvq@Oq`2WfpJi?X;_}9MfovG5auFCGpJX+6l5b`Hm_tL-lXav>&05>ujzbM zAC6#_{^bZhC^~^OP$a_UGYhXqE>N;F-PR7m)5m#e>I0Pnlp5S{OM={1V)#pq^Xad0 zAJ84it0P9Sr36FX3-u^@IRkbrfz5Mxsx(<rs_C zZ)#R=%qUvRLYn`-dy^{VPj7G!h>=}LbHD)#$7J`S2JYzFPQ@=j(kPvSn>K2DseO^p zDxJww4mrVK`dizlt%!}6ZUEr(27pyBza!pur^2k|Ch2Qg$GnW_va{_HjgY&zRWI>km9m zEp=ciMlC#xzedH=M`8!piZ37!F=LY~VkXw+wIOL+Ur&_@$9fSyOfj}VSG>f&;O06C zAN_TwHxQTVsP)BLI$aeXEvVHfKjn4ecYQxJ)vQJdUq#0HBAZUzGB{N&PHbh}iCcv( zz!KsfXN)N2>;9Z)1N>t$flOn;p0S*XLX*{$uav`$8&LRJRcZKuFH!A75ofBfkjYVx zro4!3QBSh7^tfnP*n>V10L8v%ywf*vNuO}b0{>VTzuC6+clb?r%-Wm&iUq0IOgsR%EHqGBZz~V zV}m1MkPom{;%ka1b%2~H_Bkio>FQpF(LKci7P~|`{Up0e7)90m@sesPAO=S`o*L8V z>V2xB-FB$qFm)F1?6}IYy|}c+A7o9PEB0h&E4AG-%>||0v+DVZ?iBLZ+I(u^x$Y_u z-gk**rMg#7f7$l|jWePXbzVB&wVKvuQUOEtBK6R#KF@@9v99lt2*l&rGDF^U`>40l z&XK7}<=`hHE+&Q64J8^JdE4KZ2Z}l9CFS|SYYWT-f^_bDAEW&Gx!l~atF*A9&@=~emDuL3?~ z-$(gx;GU6R&HSDdMyo^^%sBqTA#?#*Iieu$4ZU1r%byOG>^hAoZ6mem47Z#TJolph z6s;OF;0Hhe3NVoUifkL-YMW{5$5b7sy{C~-RNEChs43_}lh)BjqB{uuqa?)3#p@+3 zAPTRCJ{i18jJ)GPavI$*1mX$?f|Zl&;@Y%X2jxJdE20xmXYy5Kr^t3;TuLNw8X3%x z<6InL3UeD`oyhAHp|=mqi{}Q{bGCfF!+bKxMv7;DX-7(!fy*}oijzoaFG(f!`P*m! zq@YyM@Od`I%XAuV@T3dGg8K7n&B*WmD;wQyuB{*=>M3U7D!4F~3X-#-9=poOR5Gte$OrVgT4DAywV$ zZmp1(dUP@zq)vxsrjV|!fKAbui8f^Nd3u-ul<+t~;O+*%{IuAxrQmG=#|oFcOltxr zx;t}M@uy|3j`Hw$K`E-au`Q&XSi%L)?kf17&7s96?YN9o1Ty6N7}oPoak>o}jz5WD z8(l3VJwp5tCmkb(rrBHRb7ct}LXcPFZyhB{RUE557TMi~UK#s3zJ1E3@WA&dqy{D^ znTKN=i{cnfb;Dc-S|_rR!0|(0kJ+Hmn3F9}KAtPd=%+Gln6ZU!P~bRoUMR!X4(A6E z%cIK2R8i$Uf@;M(_mAyEgms+X+@dr}xt`CrGahq2iI5NYqt2fXZmh}ew+)-&tpTgG z{F!BI=lpdemkB*E7fN&M!C4o=Cxoc7V0WgGJ^)_@|MX$a$q|?#IBw*^Y>0_1P(_q4GO>ufIx==I{7 zHcv1+vB5sh1?e7+lF>UTzAn+Uh!N`_MLigRP{plU-2osSdy$*thjnTA39KBoItZx2 zuFjFJ9O%;JGKilG;*joA6Zl}9FOmYc7%4A_ez*1jbn~a;mRt7r)VEgxy|>sjIQ}S- zn4PqMd-r)`yo^7AGjCw-Z1t{ZxthX7#T8%9rrLY{uk1ncrlY9>3QdYfY9ffOh}UiPbiV+Dc+N7Z^%Bf9%@ zfgkRBk73sh+w2gWQpOT|U$qz&|Cnh>NpllkzvBOG1$O~g(yNkUDaThI&eity^Ljzf zG(g-_?)hBEZ)+JdYVXbt{i|LQwM;b zEst8wd=#^kKG4?^?wPl_sD`>pGWbJ+|4@M7erT)D4uy)Cnx}J?u?*NMP_61i z3nQ2_3IS_Qq~#Kkv-JUD0=6iJLR3n#cxl@;xd${`hF4tTWU;w^xZ7hcV8Z*A7D}fu z(!skD)a`A+^A4tDjfYk9%F&`{a0#6CAJytCu%xd}q*rqrn>N zh12GWPvOx%J8Y|9xNmn0dm`m+zNl9@KPd3nc#WtGd>QyAj=Dh-y%Y~@UTzIuUU|l zIBgIcwdV~aPb0RSv_t6TC8qiq<;Lu@+j7>8bmV7ZNg zB)JxHzNDpQ>eXlv?>@SmMTyhLpX+J_!7hp@sKQX}-gXIL&HBQ%TWMNB-j*#eKLki` zVCQe$Eyf}ORMj zToB$>)Nf|IKRiK{pm(eCjo)<%9K`}Pb~PGgKfUvby3GUKaHc#g3I14@bqGR042Y4a z%XJmd%GwSc-a5DkDB$N-pa^FHHCCPFk(ANJWKndXH}`ADr8*jzqWax*+~yw5sDSYZ=Hpul-^_ z`527(K^KA0H-JS+ao5%MxOOzn1v?hjvfIx(%FCCAHAT^hV@_4|vx&+k_I2Y+HC~ApR6w|VYOKcG2FhK?SV1#sf7f6JSJ0Dga?1OeQrdt z#gLI(I1$}x`@+FZa(AL^?_}4je~z#S83MPWmunJ*~uof$tfirAvX3aybEVl~>#@@%8Yl-PfB9-lE zX_51&GLnls>$RtuTRom0IId3LZSw|f9gg970#L_4Ao)MuNAdCn*2!tJs8>;alX6}q zmH=2>6(Y(22*H0jN_4lT@Aubt%n89c0Sa)e_Q2k+R!S^go$NW#T-GCf^L(tMD{w}! zYM=kvQse?qZLawP06=UAq!U{S;C(Mg)dIYA!txVP8vUip64fcuBn(OYSi`8&Tk2Af z_QPD!4YSBKCX6{Zlt~@z5So2UUKGFiV}S5YIR#uxq&5!RuT(~sW3ZMjTFG?xee*La zZ;CS!zM>SkrR#vyMwj;PJ@s)t{TOA(gOlRYRFR(pS=Bx`cb$sNtStx5dLFP8RQ>e@ zbrrHYdTNwXtA{E88ov3X!W&5F1|rC>d)NN*8E6ntkOm20?75*`0Xx5==127!7~{-7$6%!R?r?)?XRA-wHlgeBkycyJ2@MvFyH#DakE&c(ddkEPThN( zJe03>E_BlQjF@VvX2`*F5)n`Gci_Hd1R$AQBKk1yhvjefU50FL{m6UFzt-;WF(d|S zWpL-e$t1y-tb1p?2w zpA&l1J{V;%HaQHvBMq!6=!um~G19=4e5j%_6Pm1@9Ks>_+M7mj%^fbyvD_$+Paq7NLoGn1)z;IM+2;8LcQdL zU=+9X>4^yyMwB@|sXVahR#*KG{rx~*h8?$!jDD){CS|G!R>xDBISaO7b{d^>spy02 z`^CtxKTrv4k#s-LNhVVOTiIxNfZ8J~Rlh^%aSH3W5X=&Uy;T+pv-w1;?CS`b4y&Ks zpRV{kRvI(Xv*oHAOrrCLEbcLg9D#_9w!>`QTkiIOW>gR%C=p%PLyZkx3LrK1%=V}Y zAs%}t>tZ&FVI9#_Ovok(8x^fu0j*D4}6cjw#>5(NVxJr zj#jHaCLGwNSY4LRvJvbpto82nus0{5HCcdZuaVlMrfLX?K?$jueSPxAoX0z=^=Qt! z`An_`o6X+pX$)O2r=S(K*YnTiQ-E!Tj}Y^xbSM} z$vkvA|FI!y7wu^wslW}ZVI#d+9BL028Il!JnHYyi8k_LrKANTmGZs#iG24=Ge5?`W zcl_}FHM)+27Bl96okv_YjAr6N2WETp!5+<@iT z*>mCtALR8T=@jFK+cT6w>J$4#O&0usRnEQX?z3uarCGA9OX;bpE2K#~ITyv%X~RR1 zZXtQhi%#%0Khy(M6p92k-JcP{)Fqxd{xfJcYiB=d^)npm+6VjI1npfw1qOr(gIZnB zz_(g+TO{3HIBj!m7ClIiKM7+kvu)3 zcbTk$#gote@$lH`Keib9zXcz7w}+fx+rsY`#j$5JPlK3su6l-hmRK#+vX{YwCiIq@O3b9T~J=r$^L=*O-95uu4*@ zu0Cvr&=4i2LJ=UD7BA}yu{Bu8Z=oTSZ}540ot^d@YobwI=bk*&O~xLaa%1bZv9-vA z-+Z>a{$Nl8a|uI58Ohuy}lSy!LkKAe3)#1ZCa}<1{ z_c&FVCp$d-_{~t0#)t~O6^F(ZWt#`Uw;(9>q2|W>9|fAlSMQ19`0tCJ0>sXC+;;0B z4&W^c+EfhgNkYX$rEG}Z{GTQpUbPet=i!fm+Ts~0*LyLqituLQgMKFz7BHB2M`DIS|j*nvX&?q9Z z9}XRp{`xfd>Z?zCN}EocMMvk@bt@T#DZzod8}!BXDHt>p7d_f>NZ|vjD8_?ZUa>UX zggHc#&2vK%WC(Ek!&PbMpT;s#?`Ca6gHqg&4=Q)F>?C#TDxE`B;lu-uQHWb%cyr~D zWo9vQuxgV-nTJcfMt69^6a~W`$E~U$$b>Tm-qH*ES4JTD2%L@_b}jo44P=Nvkr-%E z0!z|#FV7EKvG1aTW}^VWP zFT&4x?BUZ2C~&G%8O-b0qw|^AXF98@)_~z+#opRgY$G}L1qaR!ITY864iy3ms7>!9 zhLc~3Q%EpqOP?Y>fbWh7%w|diC%{w#sJfKq{$4bI8Wtb|WHdu*jm*2jr2bw_qZ7y$ zWDoTP0E#Z2VTn*rSEtz)*AYvBaAAPb*h-~il0W~kS5;zSlh@)m^o#A+#KaEwSaDne27 zdsIvlkuTg71E{H@r%0Po5xrOa_|Gl82G&8dvc=ET&&k>}`7F&ei3#ss&akx*=@o=- z#3LbO`*M$Pnc{j6$vdQa{Wx_(ufMNJ7Vd5hH*h8(aed=@GCOBGRUtUxbjWX$4dxX17 zE5lHu+sj-soES?Ga=<<*WY`G@co=r&$KZ_UY4TiA*wYDqH*haW7l737x$G${n|(sT zf0VU|{{S{b9&+(RL?9YI7XFUZhRiT*Hrs)(N{>$^v0!?7dOACMcS$JBSwOemJ3YJW%Y?7 z9obKJ*r*VM?%_3g%3Es&ud)O8(m|-wD7NCtS3NZvnZlXa$a0D>PvEHGRDcn@n+BJd zeS6SF&TroPFPj{Ce1KpBE7~Q(=qezH5LV`-^|oYkF(r+@%{*4NU$t{$3*00L(VD_$@QQ{fu40;@C4F zx-1WOuwFf#p<-P3jidHrvRp*AP-$({z*-73;w(mTB^I+Xd}oU$GOa+PI|w}D`i94W zPBYE9zm^b^@E+*^GubFHj(5HIVm!H15?Q=`J=l8D)8SAgJ1mW1rwFm0%e9-f8NP}k|J9=e>Xum#vj=sE z&bDd3x6k2Wkq*TWt_WMi<46vl7#yN+#O+P!SM(>{M0#(}RoLCmQP)r%Msz^Q+%jcI%M?&bsN zZke#25z3<|gIeX@x~|W~{d9_NRqC6p4^_0m=_m0wV}=3cb=2{NdyZ=$SY?$>Gn7GU zHI5!;?;01!-L?Xj+yDOg3U@3q z?7yy0yh`9JxQ3?a?AVQhd1Cj_3(cASA=B@Uk$?@V^cTNMfJhE5ugAWZXWX!sl>#CN zy{aaq9^M*oD=DJ|M#D6wyK4JOY)wLdu5SX2@QNSN$YHn12MpC$=8l2Bb5)5&*z~wP zD`Y+AxSU2In@C$>g7|MmI#i4_fbjG0-nSJ1g3=UGdzBdQD~bu&#h4?i!3t$)S1-Xt zF$`%5fhzAt%o2~8o9*fTiNxREgGr&(A2C(^W}08R!-?7*srsqklQqNO(^%1HZ5w?x z?iZF9x>eKA&*x;8dZPn0cY@SPoSlx(FpUT%2E|h>ZBy@X59-pa+tcb~h_adwhogIk zZ`g+QLUcd!{V=b>5638>sXhw}@^*vb{nv$(+Q;lW>B_`%%7aUm(}3>n1&H?PpuYrWomE^_2Naqyf3X+8*!S+anL zJOspp)s$EwvcCAFmf2xGl}t6a9!JqK7Hty$6)YDXbF-!vs=^Y!U*3YrkVxTM40#>I zmw$IU!&fM$+3zf8N5);n+x+xp+}RLGt6VE!skJ@V<4bUVil3@GeDvuzO?F?X@&Wpi z595Y)8#(}S_zGf&08v~N@N2>dZNkC1V&ZIwki`4fkrsR*m1`o8T-ag0c+J_Yaj>mDZOTluY(LIN1)dg%0w*9YF$E z=yr8>TtF%>jg3(R%&4-0XMa))@QsAneT}mWqpm#FTS`+P6v>IuPvgaMCr>kXW$~06 z;ecjU72`EuqG5~#6XmR2314Tf(zy2D*PeWj8BTsjE04G%ZLkU(vqv02hJYU#MsY*&17Y&9F|KpSf^<#>NFV5ur)60d#ksOyui=nC5=G3}2Z@ znJePwj?c%%V%@2sF^b8hVa?t!a*J+?Y;2*M*{OS7t827hd4NrtuIKx2`xtlrns+Yj zv8|73Wgkt?pi7di?|rB{s*&8@EPiSpX1_bCj@rfo7|Hl}S2u@R?7q9w%YN4DZv^_& zVrY|Yhls(;x)scNA2m^P^8j%9)4f^mJ2p1_eAA;O&psq6{B%z=?m~iM`Jk73Y*UUy z*PvSM8P3u~byY8VdOVYf@yQspeyuv;JN&5$(DW!<#aIppy2*FjRLnD%*n@-V}zq}CpDOl&6~ zHsiE59&xrns5ea`l$;7G$5%O%|?r`D{6$tRJF8piY!}$`l>aWQaMSsTfQNxZO5d z`S{#ZNzg&?b&6+LEB7JlEd8s5pZIU95O=#nvg{;9&ni^a+n`Y&V-|2s=DilC%%P2m z*xi6hwY`dIpg*#MC9NK3rli|unP@yGfbt?RWg0<$F6}qmPs1v_vH1PJ`2z|boJ_{m z&?^yIKv%CFIG^X@Cc~zX zKGa5P-)kR;S&Gq+3dbO<^Ujg0+a0gv9v)D_fVH3EOQ#UG)Ov@1oKjILEYGi~Daf$d z;$e{IKpBf+^LD~91;zMoc*Ir&+qPpTlL_6URx9KBXGpMgum_v%mWRF4Fqaa#YW1ao zBttXgoW>Z|{7Uj~J5u79dP?n3X`TU~H|C@wDrB@%K+`#{b_48Dr*I2z`e&8pkOzv< z$r`xs13Mr?QIk7Oar-VA@bo8S(VXHreEVUNzK^yLEf{cF@Yn|{^V+xN&DswaJt#sYB09>w?V27$MGMU?d&e|=X+$N9CKUpz8p9so5d-_nse;KnMe zHk?Gp5Q;(lhRv&@BK-E)thbjLWw-d$D`0}V7j9~WX!7x^?0kMg8XxUHr#M=z|5oM1 zI};)Y2Hm2s!ODx$b1!%uF-#T7Q5wnM{i~eb9wUgeF#sS8kdKKatK@I*n${QRYeF4w4Q~3=jpmC-ZJ&nT#xTt1}BFJHISvnz4@1k$O&7Ikv~iEDW zcpyl0SRYUw3P)u8WezyYxDhnWqN*-@sQ3l23Iom$jXELKUGltrnko%@+kDHr5wCga zU=V?lFksA4q$xOiBPcOVdBw?9Bc~&?zA}@%`NJd7{IeOux>7}1Ham(Z#xW-o(fhz{ z2pfyr^sm8=R#&D3?J=3yuLjXDMa#ehoeq`ObKB%V3D2*}M{E1*sUO#MB>glQ`XX6W z9O3+x5^!Q%jQA|y!82h3(DppLKi^76>-LDG=mC&Mn*r7BJ4#;nbScaZXV_^I=BD5v zR*_}w*|_yfT1~&7lx((Mo;@z~|#ON2wN{$PKi|e$}*8Ervid{k_mskuN3n?g&XWR5in5bot^qL(yyF~n1{8A*J z$XP`=*NmAVgkh;tn)}QyBpGrb{Ki0@ieMrK{T%X2=A!^H4-Vp#>~fZkwcN9!!^Iv} z$oz8uiNk(QX3&X`@ccN68S;VOu-WuXrZX+Tu)#AlN&Nr}tveu~l(Xlj zIadwsSBpMxfsUQQR3}+jQ$!f#V8twh4?AA20n~Zc2c^-C9+g9c+U4S3g^5gFDK5K; z)#6~_cT#i+3QG26#hA&8<@#{+47ptb^JuHHBn*rXalcIwJL^kT4Jhduh6RcMGAG=K z4F7)%&N{sVLA8F5eEs<0xknjKPsdC3g`WYH2ESy@PGqDUzt|1~Vkfgl;M9cupz zluypg`-^7Yh~!k{%QIV0Og}>Er{O9dtIZ&%%H$c4PLF6xhjwWzGEvs z-bt-W;RQvCAnrv_#xk zwp^*u5Z$@}25t?O%TMTE2?*IXSvLiF3D3KE1PfA;|@Zh|bba;ZU*e)q=3+(OI zjN$&aw$Y2-jNkXfXs`2j^o{8lB+{AMonV=Szep-;<+AlJxrLApi9lT+Wb&iq2NDM4 zV9`|vMD;9r18?XaElLdM)8r~Ye#h{}p2;Jf;1rLkTo9jjdlpNT*@7w^jo+WPuR#fdEgfwgu2jsrWQK6VRbCfgeSs+ythNocnBV*n2D?L*A=v zf^Q2xlW{!cj`aLxp<^G$#n*T|wGK;IZi2tlW6MPe2~i|Iw$)&M>@r*CHC9?CqJ*)& z-$iU|svq^)+7zC>5z^M~otmZXnrdVs5JpwSw8C;{6cg~{gl$o8!ce%Rc3ny^C)ebN zlw!*agZRk1Pj$GBt%~L71$F5ec@m9~#Kej!~97r=4mO*Dn)77KUS|W3~aO zY!+YjO2h-+9$P62+Qq|Tz#LtjdqGPwV#{`p%M!urRht@j!4 z@5_CG0=$-m-W0xWGVV;GMT#!dTtYvMoJCc;C!_g=ig$l~^B@lQr1+Qip=hTro0uL>I?a1&Y$tEQD9kXo z0jR}9%WV%~@L|}J>ST(~yQzN0;nf6afiHH?e~aImPb?>v@)KINMii5cYzj&jBHN6| zUms5OHp2?R)xB}TUv86ORw9u3!!gN7`=zNh^s{Xg9L+P|?t;LNoujS_>S3Wabf5O( z(M2%hf}&Aa0oGOq5iHk>mjD0-xIvzVE>SS=00Unnj!?~v02bfwoJMJV{giv7`v4Al znxdF=Dm_A4|It*6R@ny-)O`=dNg)TcL!K*u|5ssZ#|f%1`n`u?vs2!Ip?3x z|Db*Odcu)poJ2`^wan}m5Ov+K_eW+_^!A;RoWWorQdyAu90fNnX!!gK-73h1-Y;Gs zrElQ2+nI^mZ6Ld5gC4L_rWIb$Q`D>388x7FNc*z(x&mT#97GAuyY0iUB0MTFicJc zq~MD}u3*-?m)u)BfDg#6OX2Rp@9#V{r01w{M3c2*&oeC^)Rr7iLyZrG`_3R|)Nk-T z)Qwz!?JUmpw#1R=GiIp0qm4Jui&IS3_)zE7r#qAQWK}xG<1IvV| zWR%FW$L$A%$+L0NzN}eA2r z%R!<3^E?-VXX)W4`>qK`XV6y>u|5hRa>05NB_}uy+F7rYf7}ha@#;n+Z}94gF(Wrv zkFKRA0ss>$o?Uc$1Up6&5=#FZTe+ZI*o!v4vXK1l9S`r0tKXjCe(zwN6O<<*=7N8% z<#*`a@iE6}Ke9i4$y9Te8JpoZrSrcxDl@VAFB?aOm#NaGIq387-nIU)E9dM!Iqk%cF*= z-&$JX)qH#^zQq{ zWz@6y;$BlNy1jHsx)2D{4J(CcRl6uMYgen#o>pGms2WnBaViVYN(lrd>3Vb&EPOp( zXE#2n$UKIO$MIb9mhm2GZCEWGpxwku0X(&b}i>`e(gJArA}=rbjc{g1_Y#RXf~AeE~ zZUVjs#?*L>v$r!S;hDP{XoSvDI^YV?MA>b_8H3@@^lgv7hLO(fng0*obmn@n-!(dQ z=klnC8{dGOG&Q~729a?P^QF=I6o*ZHmvpaj0IAu*zpzBV9yF4uO|iEN>(Hr$=plnO znlGfbhS3?zSpTe9E1xQ1=tO=L+_<9cCZUykToWc>aHN+rtI&r*oW~^c=S*JiQfe<2 z8Dg9|;UrY1kgw`!dQ|}yqib<|zX57&qd#z|_iH#Ll1%b5mjzo%w|JtJ?_QY|a(LVO zB*!`-MIm<=4~kfiS|Jr!DZX*=-DY}NkGVKXKgM*&&xZVyZvDt;`Z*$QVc)tb1#LH2 zXqS*7GA3mwivg<4w4YA3&}Z35Svj1MOA1Z!wmsVYBk^cLfD>vjW=UJRnpBPNl<@4a zvOv7!Wm;8ehS5rQ$#eng0*puwtuC)5vX;<&QU@Iz|0Rehtp{Ki{p!7O?vPx?$3JoT z40BPeS9bTJp(rGW4IEA?N==45jRY6EB#RQDC-KqIunEs>R<(KDJ z+{}5_Jf{`fwl>>UJY1mJvefez-dpVAfbuvK)OPKclgYCnB+#M5I;7OHKCG4rvTgrC zX0?LeK_NjYo!|iqul_uX4&^|$$wFC4kk#==@{&*~z)!!0WwDs&Npe86aX|kGc7Pz% z$a1T(te-J*cO?Bdzb)=yW9PRkz8r;)q^C8Xs|Z+lErm$-+JZ3Kg$%&e11pg%MI=^B z&|U$y0DfA}#wOCIED_zp2J(WQhmOSsK~ALo)p_BVN|ku&YfLZIf0~Px{nqOK!;Ga} z&mwfK3F-J5cYD!!H%8-SFJ$}Fd4a8AG{k;k_+QaaXkOu^Uuf|#@Ljy z;k|HgHH|MN;9@**yv+h|d^QG_yUYj2Ic7ZmQ-4zwN7PN2(i5yZBv@bU$MYuWGeJ@d z5g7KN^c%-!A1lih1JA&&?LXwfDC(Rk_<$KM{Am&tw&NyGoqanPiNsT(YFNVDNcB)V36xIs7AXfW0e1k>B70t2%yjI!Q$ ze1=IjD3Y(jD?tUDoW0u(rkA7^5I{^;!n`h^L~2$k4h&!dLqI>-&HM@6_Cr7=!`fVZ z2I$Ulv;jtU$eSg|_aPR*e5XH(oG{tr-leq`gJKcQqW-`e)nF7rq1_ zxj%)Zf-!!5DLMl+eRR{VBGwoV(P0PAc2QU)E|*NC`hP#BLluKk&Jf3cWK&ql~;&#IB@`8AC& zWS#&t*oc6~7;lX0w1hsA&kLF?wI0DeeADLaEY_)M1Glz^{_Us6L(7ekq1n>;IaFyH0trfj^F$1);RKZ2%$`b?CB>&iqKyR{TEhZJOwZn3LhJ=psjQ`PrHXJIEASRbTMi1+t+LHrGEOCls0;q)w zW241(W)QnHk!le>oqK%sRRL3CB?Mv1e z=DQ7}3BKVGI@DZ%B7dzH`}%rT^k(dAD9C*I%9{c;Rw$?UUd&*iu}ZFb^~ypm$H3N` z61<%93TOfp5sLOD({!;VBn4A43^TTW7Fv(O=@?z(!9ikoEYi!{HAs;^Rou3flOF}d--HQFz3!O76YVo{Jw8{OhFx_S* z?yo`~hyNAZ0%NXg#1#iGl(m9u9?C_ze^}>(6n`&*u!^yITL<4TkBN z(bk7c(#fb1MQ0?EWHfX>q!5ipAT(~!fLOvTo`8j?>NHJqI=1cPJe+{?yF2ZVAHJgJ ztX4#|;F%WXAOSnCxE=*EvBf*`KN_7Er#RL3;qq%!S{zk`e@)uZY$AgbF~eC^4JY`2 zp_%q^m0apv(J$2bxvTutlsD^aeIK>fL5fj(o@p`DUmjON_%b-x3AasTpR(GTNB$QK zXU1abaW9DnAfV@nc+O?l7+WPD>uqvx(VSGw-blkOFwFzhK83)3js`b#U$5wTefC&f+ODbUE)>xc|eqnB~d{M6!{@@Epav8B5bx4dS z@gbL9ULPID(XxV3;e3BOvK;dU@E2Eb@)+75z;sV?5}*{eQ7*MI2X{)K4OJSo4L)S} zMDIW{xANB#)1oy7G@R_G8YN4IdO+|>^QqIpN};h62vB1|RI(YeLC@@D*?ST*AQt>!BpnJNw!O`yeC6}z_;GZd4OTTdJQr1`y@s)}7LIS+vm0&h{O^FRD8;MlbLxz@q$5?x=m zdgV|+GGuk~sVHz8Ugn-Hn6Ljqgc?51c9Q;y1CQo=&$y_>l20{BX5n*=F7Flf`-XYi zH8=fcXR6B!d;qh=En50lgb1rx3tvsIu$kX1w)TkWLXcey&)t#udUwAbbL3jARKc4` zJ`da`Vb1x^@Y8=9zw>nLR&NOHXh7@qkg*QzVvco9zD8FdsA$3SMjL zu-wMStl?R=VjHt5u6vN@)=-6xJ6FVYm4TE0x^v7Oku;dSVFm*hXzT!l_lyLw#W=OP+$2nw8)0foawFLR%u$y>q8!dvZR98Z%nZNft7WtsJYvTXH zUZaQ4L4U#LGfh*-6lgA?$G?=Ra8{m@qrWM_ZhDG)G3}1bz}w*DLUrCMyra2s>G{6c z9#be{DwGYKs*V`GyGu`k!9!FeM=X)K$7-aoWBdQ#GhBL6GFA_8d}2}D+Ip?kxGTYX zSQLb`Z6E}bU3*10=vS@plhEUkFl(Mb{QDRbx_8cFcQXBlaE9LcxpwOXU|!4?CD{E1 zrG}Ybxr0v1b$?V)$x+Nj9u2+-F6oj{-T1;r&jp3$khdPlE&y!5jY8^12+12n19%*G zjLd_sElSlXdvs47fnFxp&qzD$CKepzv>@!j3Jkf*)&mI z>7<0RNHrh+TVz^26CHj=zu^Lh4lv*xCKW}x_-0xe#k~ew1t_j#lub#?A zI2|UCl5KKv+W2)WWf5bRzTD8)vhGz}3&;%${(xWazxMR<^3qvveO@vpI0@_(aCq^V z61j+1>EIxG9}cRxjwpMTzKXPNW#07-DhQIo-dIU1+9ldSu`ZzQsjB_F%ji`?NsAL~ z2iQICXh@pL4>TGMa6-HJp=6475+-}C=1D`PF9{z6YqTXLP395qodACaU?f=ffN9^o zR9jqr?+m>7#%z8Pa>L}@$&95{;%zi!!q$N4@GjP|3X5&l-Krp$)>Is)Sp?!WmWK&0Pe@h#<%w5RrR`O7i0g0=oJV4|W|U6Pp~`^S z?f3-d#WEn}MO`loG*8`eR}#XLxu88wm}+DBPHDK@R}m+bxyo>YMooxA6uQ7J_oF1yLDfL#8;Mt=%NNKh%ceHa7I z=4SAHNx251)98klD$*p5?loNCJEcj0@ATut#&!=I5t8UDu+-|aL+9xY=3NKV6AhLR zM0yJ%o<5+p-H?wno*&L$>2cwiU$sP8Tg+!!aWy?>l=U(QndB*OzwbLq3|l36HHy7| zylIi!%z54uCBlfBr!%cLWyD&oI$0{FAna zADidX3b#XKAsG`{AxmTdYy>Kdn($UKQE?$lZn*9*^Wl|;L!Ha|Bhdx&>7Dk(c9=fm7k15A~WezO|y|TMmSRg=q8}*g-7e6wx z1N+$a6NdGTq_^DIoo)`^zwhm{)B*5i^p;m%3*)3GLsI4_?Kf{L%G>7~^HE7W>H&E9 zz2;E2U2#aYy0;0Zc~KwgN%sddZ^91}s2h33oUxw>Lr)HIxwH)3HjW%q4lp zieg2S0$h^nk-G$%1ZglCA3yu}JDD)x1xjFK17R%Ej}{q$ zvMG2%3frQUkqD1Vo{!&ezo#v%bWzUg2#mDW-bJrv1fuC5r)q}C>8&(|TleS#1H_I` z9cIv>>J*vgj{O}At?ggIfr&#*=NPvKF;WX`(oWu=C?B{*)Qdi1Tk%}v`G68sVWiGy zMG4E(cxkuH-2}k~sJp6CI*=5O6e-dQAJowGiaWGM?_Sv;V|X`YHW8-)cN$rzQf8yd zshsR#<-$1m@+>(Gka{3d>FK988A&Z|ctfc)R&J%-+L$xmW%L}EGCzy8TRW;>3q5Q% z)GUCHKzJ5KJ)9diDN*j|$NH34deaFLSv57&=dt zE3O1AD~Vsme%RURMKs=w01PSH>QjJOJwOdFEb3>RoI#o*OE)i81mH8YYZu2!z|sfu zc@DU`)Mv))BVy7ljFq-J#Vg@l9lvm78JtgwJAMjbpw%Kz|?+JP&D z=j%=$V~1oW;Y*!I_YeMBsV1wSH;Qh=>A)~#DG*4=D+kkHl3mJNCV#3oM*COLs#Px@ zq7i%%olRFUBtm5z;I63z=>E76sKgwhYsG`opfM}ZDt8B+|G)WM z-m@S4MN<-PI{7~7E3Fbcg~jZAc^#t2csFNJ%~P9E>9&`%n#%m$2zUXcOh3rtFPM@5 zvAgWDc~#AoC<$Tg>ms~rVb1R9>K2p~!icBPZPX>x>AQN??qrD{64y6f#;Bsrbd}N8 z5hwRlO9o@5KoKGGN-uLyN^KVebn;NB-HiI>2_FlTSGFv%3vhe!7t@^V5TM@{W0gX! z)T1Rl7*(DBuj<|_&zmwC0jxLNLuX1Fmck2AF7?YAba^z_SZb)LD@HdE0C&_>g;?Bq zT`x;QsJ9LBj(##w$Ijw6P{>?J=#W^3^T@8a7K>H;A53Xkw8HyPe z5Wa+o78~cEC|Us^FdL~#^Ega6NPW@`ah%e{ZxzRwmWS2jS27Zw>wC)=c9m5?ybaJv3h3hZdH9dO&59Avf7e0o7I7<4)VZEr8jWcwZ1xCiJ`ar*l~Ne+(V=D{17v#WnHfNuTsjXx9bl& zQj7j@<@mgo;gs_zNdV`#9rJd(sbF8TUR)k1Y2@?vY;_9k3MLc2P=Umg@Pkw!AT1`9 z!a9YO0t-epAfBZM3UB+s&Jag9br?LhWbGD4Wf*IE(mP<2$Lb%nBJ*s4iQucu#-*n< zb^_-o^)-Atz{b3eWOZHv-$^L+2%Omx>_cfTC4s(LAn1b!$$fj-F@ePOtJ^nWVns)@ zT6KDVC8A9(iKMm7aOt{z=;AJgqB!;%#3U!}`j$MMVp-`)az~g@{(s)TfSKG>WiKqNW@s7Nq*psC}P(qNle0X^b%-(jHnbTW`jE zM{nxA#`lVOxgx$G*1H%Bo{L!A;c5!FaZM@03NFch>ZvCco6hS@TAMfYf(PA!O>eB} zz`Q7pWBt^WMbuoS>&no0@~!E$CJwmErD0;B_t8@1aMnbNI3R8{egh#BUs`PW35T9p zy50mEsM}GCjgEsZDh|Mq{^@1#4@6V~|A)f^!6cY~;w0ioA!g~*%xoFYkNHDl$o{yz zu0*Hd=inwoe9c3OFQI08TGOf&9XUdJGH(~lQD}JC}(;!>Ej~2tQBanQHaJ>m)qa(_lJB3}>pIeO4FRt!A1u#rvJ%-923(`Hn;rp<(Y4h+NTG_RS^{PUGH zgm}e>7o``Nj=z_nAyO}a(qZ{WGm_nAh4jyfol^0~mi8~ISMH~cc_dvDc?8^Ta<-&( z2WQW4wH}XQra1}fo=SF*IO;A=?IgsUr~+0dbK!?7kUlv&OzCb}DL7;Dx$<4ri9I5x zk+G3=bXAR0yyzUcKqd~{yTGektptHV3H%|o%Pu?GYUZXln7bu|~_d166T)V?{549wI2) z>?KkGz?sREalDc*_01DJ@hEz)cz-1 z-z%huI)NLw-vm@BkOo?*$T4N{3>LSp3X32kYwq&wMdAUI^iup+%RgepC8`d{pul>{ z(e+xi3w?CMEJ;OyRcpwW0YLxk++Ut$<(p`=PARYnq!dlNY!FE=l8U`WSzz>{9tKhy z`TKvoXYxV&3WZ}jm;@*hVe*Aj3yvqu758u;$a#esE?JGeMPdmF1qA9O=s1W78|VJ> z5T;1{H&S%1rrI~a-FI14X-D z^04TO)Oh*L!hN{|a6b;ew65gJtT-UFgQMf*r(XL4coY6t&fB~ui-`vYSs|_Vn13Xn zyA}S+#f%`3YC&wINhIOJ?%FKRvT)pRl0#0z6x0u0P4}gYj{^J> zb5l=mtWbDJeT3;De`-HF(yXPkZ9^1VMp0O#G|z(*1!4m%iKirQs&Z8-0w zC>y8J#_(j+vR0x!XAb|20?FaU4WbkzoU@GMwE+kdcnA*u&yR|a$oI*5#$v*NkAMg2WX zC{DWWtxnhpu99_5%G&K==`l^ zJ#$?Xz@8wnmv9~5J_V`i4QhbQu%078^xQk=e26bq#%@HHf+3shOHqxo{A&BJIn+Jm z!1_V_&?k^%qS;fQv9Qda0hKU?64%gEs>PjfKtaP<wF_WDNdB zfWJZ5RJhT88K?bZ_;=4b{ZUwOJmdtEDa0bWav}C#c0*7u z^0y;V)X|@C`fb2;p7@a(;PKGfIv2_oLc$K>Hxosgp5LD^IeAJ^tGuNJ{ZwGdu6#4{2;|{6`fRrfH+S^S zUeyMpuH4<-4p~7LJuzGN2X(R`fjO0x>T4Q@?ziIh(|0vDY=Vy%@2YAc6Y61DMjDqzPKm z0Rd^I08{3?lY?pVTykF;hzcgFj|&Y4?*zk2IcbfS9v(1KCR5YLV4xQIv)`-8rG2lh z2ASO*I+eZ!+IYrbZ!;6+snIOS(@y6QEx!BQyHh`TYHlBs415@fA#Dy}TOq`O<1h=#OQtUs`# z$IM9OQy&9UZnbWH`wrjiOk9;7}II zv`SQkX>o&?h9=dP)sIsePxL)5IpmCjz5_|)h2A#K@><6pkt}}2zMKD9iu7D9HUN}M z+c-dYLP%Z!|0xUuUw-yxoR?(XY7-VHAMVXU>lgf4>?l;g000BDL7vJaltf%R{{RYh zn=t?>d-v$#q7!Jq2L6Yo@bbrbIugnE7T%5oCBjZqA@(<3|IScWno@R{THOIH{_^BSnxmC;JO7)E6xD1^JLeT5!ds{kxD3yf6Bc$dlGPfLu5U6Z zX;QbMwc@Hhgy2SuJWU{J2siy%wBV}k-k;O_t7EEkHkr!hw(i!OH>q!018KMb#p3 zGlRH;-B?TY2ze6L-ayR?R&z{fLy*4M$mj_i!K`%LxHrDCVpOo`& zQ1$ZHC2DtKrW4M$`d%!J6UlbOV_blQ^7|}?+bHtjn*lGvGGkvSUGmByYUCZQwjzqy zZD02H7jYD_Z~bc({NEwTWAVsyDwe7)dDZu`WFDDhuw#lJ&J4dXt$!I7`3=V|9OK+6 zu%T+$_R0nh?O??Y4=v%{V3R9EPGBsc)6ycpUB5ZCGYZ!=y?>8KCv`GHzoQYQg34{s#PCqz@3ZOM-a%PSpAb&-`2#iajEuf#fhYME z2Zkt!mC!{;(A?8zQ^{3h*x9Hu$1y>~r9P=GMpBAz053t$!5#%aXU2_$ z1VL$`34_8kf_6pgfCl0a+$d(gAtiK0EcrC#YhU%6uZEdq>?$a)AvG?T;BKU@d7fKZ z^i4nh7-GB`Yfgi@%Udm5ZKpHIN`U51RFKuo(48uA>`cGs7f0P}*yBwG`#I z_s~`Cna>=Yy?pZBZgikMx?_YF=@&5gA=9wMmnWT$C-ea4-`XX>rxrwW1_~uTi5-pe z?PkN7^wCpHmr#yaV95{K-;vK4-6ne&O`fG~zroJAEqI1>0002)0iNq_Lw^7S)eh9H z=9F{e<>BbPqyNkLyj}ru+~y||k}7B*{+eTiFO3%>Q?&YLx_}Z-0!UQZtSN_BLIv&c zGwL7gXXv*-kAYi4lc^z}9$LX9p+0Fk=T5H_KInD-{rhfJL6Faq*zcRZ$Sp2jdmQ(5l2ox}ySC`YQ`#{+0yF>r=SnzJfJTg!JgNfJTqY z{%LHCx!Sv8+l^M58yyZO|0#Iob^Y{+n?l?{UafO?Z$3P(B_rM-BL} z6PNe|dJ;7efo^tdjhT+Fxt`?N4pg3Ic2vTpBxRVw1$`Z6-;zd+ZR@N-7(>b+Zm}wX zW^(ry7m4ea`?BMIYFmOnRSyS#F0UehYpou9gZ3mqtW1AN{?Rj#7;cOfEldh4+=sO3 zc3??RUm}!m^XOmJBJe&-y4p}=)Z5&KTCOIVceyWdr+kimZSOrE;YLFCbfpZi3UJgp zYrjKtEl*~?XGRrVza|eb1uEIA9vGYQoLITsXU`ZF(Bx~Bf{$Kokn>X^MZ3PVPo_~` zmuIIt;Ty$l#lT;c3vwx1WPwO_TSlZY2L_~qL~JLIkNqc1!WY8GmbZpYazoG55CWo+ z+%Kf0fYQijoQH}a0_FC8&8T>K`BP1WVa^WXOq9fY@hFTwvus|5?p$2Yl@@mzr8agO zs~|D0dMu#d(sBKk%##S)6MQY2Y4lw5=#dR(N19>4Syk>{-rj=iajaSI4YP(|p@FV* zD1=Fzt040JGwPlH+cm0GoA@D*oy|cutrYu;wnQ)C7{@oZ=Ab0>sZ^|^*!NfBcZ+0^ zw}@hp5u@m8%g$}hLV~F(A$F(WO|Yl(`_2a>A+`+2O|H^xmM6RBkgj)t^xZQS%B6ZY zC|NHV6mOyqy*q`1{QIN=|4W+++_1U-I=3d`vF3r&54H{RG@-!%xZtP@Oa^QuSBr(J zf-(or|5f>0m6X%l7!mN@1NB8SDQSXajl6jpGM~0Mb{LAK}4eb zl2^K@a)&X;+&&0CEux>thQWxSI(Dn!nfo~RIpM19Sn580OpS8C)s?wqN=sb|tdMC! zF0v0rGj}x(NyS^GMneySalNAYtb4x7-Fi#q1CT)jn!OIPRZMDX*`t|1#J;t^2Av@> zsW@4AOW+@?^SulS51r2Y&Hr9d({NdRD)O~;$0}EK_Lf=lwR4(~wWo5e>OZFGd1jE- zS#k_ws2>^zg0etgL5HM1j$jzD_mG#X=IuUP83mSz-$)#eZ~@KW z;b~cXbgh$Q`+57Uph6Y%&RE?J8M&3QkIa~nTZvs*U$Sg5fMU^a#0sT>t%cDxq4&&@ zsn2XEw(l_*Py`L4iQ?5KBA@~@ZX@pS38sZFZcFy6;!J7CmZ`(d0UJNn&qLO**Q3sT z2Qo%`6Gm|@+gK%aCm zC3i8BD9f%t!W)GNtNR^y%ReX4o=MLtzS2iqer3U(wLgQ$Jc(eC0!q^jYY>Axjajp+ zhBkqp|Cmsq_9_=YM(i^%p@K>&AV+-Js z2=%}g_Ie!1PN4d9tk_Dy_Fo-SzKVBS%_Z2AY#L2m{B^@QbjGQ{t7u*@L$gZOzDCwy zq-p|ohFr!IPA`7Psy8TrXUUPxfL5@RSPp1}R4YL+(H)IVPISy97 z@gTGVupgtnlJj%95rG|CnH$z-)xC!!vBXjBMVDLY_By{HZc|IK{5qc`eQMtS13N?Os*wv5P7>D976BiY^jE1cPESj1S5{ZGw83yf(a{VWHx%G!d zsq7RDDVOvGb{`JjaYdcO?!2d1SI-A2=yja#PGV9WiAycxw181J6OuJ0U`E^;8=Pd{!sbwy#XnS`>byy~}( z%t0L}XgiIn;gA;&VHzB^RM&RA6?jwICl#a^$}?6@a7E=Z(`2)G_zSH0bxI}3Wpb3C zpHf0H8tb|l$_fYN;)=f`L1@}1XmPW`$&zykRfJc{H4h`A%#K5QRERbay}Y~ybQu z>}x9|_}C%tCH#RL2xQ7%o$3dcm-^`K9>JH@(gP&ta$|0`_B~njFgGnHtr1_GX^@x_ z`g^YF2U+P<#+IqpvC+-McOw>G zI8L?}t+J_AIUvJ`*@awJ>z{8~p19?d*PU+UamxOc?ZA><*Q2;PDDW8g!Dst9!lmOm z6F0n#KrZq76fCN+9D}F(x1bf2P-_d$ACZ{lGc3MDSuI2&t<gRnTy!Xu3&TLX1UlZZ$1_Q@s2B6`OW_8wa z;19B--IyQ!A&dJWJtof2ZR25oqGDjrntZCYC>O9niyU{<;_;6oS z&$mdOig)^w&sy49k@S1TVkE_JmGBSA#H|J0PRNBgh06*$ar~Y??^4Hs zpN2&8W{`uwo-H$&XOt1-$QJ-;@w)9uW)HIzLXxTITc+=i|5MWNzg~P4a(`3r9qFZa z^Yi?Kgx2OTy6k2z_DM2inYf(NB_Z51K*-&UQ(rX;>30?j4W`wje9H;Jr|wLer*o;{ zcf18uaxK2ZVO=@84a{ti)2TP*xW&t^AOg|9c;>?QI57?_u%ezI1iRr3Nj{%jq}>N< zjl(Z4d-r&jk_Xa=fHdb+Q6*im@%?19z2^1ie`;=GPG!akvd`)577e=gp~Eeg=sX9* zECm!tBq>zo>McO;^9pi*PGhD2@Y^t}9~6#gPSYc#EQz`;Ku=kUWqIG)W@|}UJX(G% zClIR@mZjCCk&ZNt-CBnn9oB z8z6>N&;EeC0~iJ)k$x4qj^dk~byYDlci4UnV0;Z9`6+#^QxKt=d|H#jo-0thtQ;@MdCVV1d-I^{-vA+X?2huRq)bh#qzudG%Ihb5)W2HRsXNVLN@ym6~4%@ z>6VoAmObosb#3csKi|F6v?2?B%>r~HUy1x=QyNDFD+B>mttnR-Zb zi`skDk>op>VUr|Lb(?Fo0n%p@nzb*J)PR}jf4;=`MuLW&7W#F*3lU$uHUKu5>jC*9 zbpy9KUZ08V8De%4n;vW&CI|S)dV+cfp!n+C5_3A28QKQ8X@R5OK9>F>-}p0`_eIZc z2~!z2`#&U5vN;0;hktJ0avne{nwhK2yVNB+J)gG#r-z-U9aMk?3T^eZ&r>%p`AE*y zIH`nMs6IVpG;*ODGErnb<;v$`b||#l@u{=piw$`XLO1h+B*{dC6>jz;Eoot#=Cyf> zrd1wRnQipg-e7`Hslh*Xlegn}fNZ##!Pftk<47B-f1-{FJgev46gbk&QCUsQkh!Kh zo&z%J3$+rA+%ma94K#v8D^t&2N7B$5uh6EDO#&OR%@Ras;-&+ImPDrs7deb9RI|M> ztu*tA-{v1x{1!ay)xI5U4@!cBH6L42eNO;ObE-}&Ad{mGt)8|lQ5NAo@^Ao>Ayp?- z44%=?I$r%H8{?qGs5K|)e?PU(@EWAmUbf5sDUpL<0ubWSQOCsDU5j|bevguocFl*X zeA>sqQ%}t<4iC}u((AQTXtBVNrGWAhB0Le+m1AvuIA|drBZk9G!XNuAx0q^VCp*V9 z^dQ;?ir*aL4#~KIQ2`hfY`C-y#np~Xb3v2u(R)t&fr(yrF0-PFQWP18cZZ&m@B&3s zChu;G1Zn-uFMUw~YFmS5C6)+w@zRv+MW`_sJA5ezhmzk13%S*qa z)l6JDvhit2x|ZS~e)>pA&@v)2oerxQkR}x(pmVWcZ8LOeK35o479;?LXVb2(67%<* z)gK;^R#VwCBoXnYW3`>|RRDH3O#>u-Tf4Sz4f|O> zEL9H&b=4>8i-mn`stN#&KIv-Q3xwkqlh6}ktQxhc)9;RNF9Z8Y&n1~g+6q9D=_jy| zK})cX%>0Fs1j`FcN?1zPSW-*e1$vOWW`nmIb-%p+(w^uspBeR}8ZS8+^pl{tvd!k% z2_t%eWktjf&{0B=8^Cyb1eruH;EUPyK`W$%Ot~eC3NV}4FY^QsPXK_jwWq(JM zvbPHl3{vhnJNEKcNb&knZ7LsAp0ZAyCjdAq*3XjNCaALFk~f;dL-ac7zKP0W*f?xt zdflK>-#mor7|=dZ?G_pSV8x5A25~m(O(G?@(U?g>FGx}DLLLM19 z+@Iy^%6!ggO@z$b`Q`ZRQ@RF*>45??OU_~JZ73D>t5^<6=@BVWV^`Y?*92N#Nw7od z2;7=v^!-fxY~mSO2W2Rpt*-D>7v*+ou*>q?iqZJMIX#_+{BY1AOtxzdtzf5FNb$mV zWOTVSYa~Q?D3~1n=94zAt%-DIj1Ci-%#d!5(Lrl9ETY=Q)?x#F`XlbyJ}yC&;KAsM zdzkb%5V~x5pc)EecEUkvq^QRc{UtI`i-<9#0x)iF``%QP>vaG$Ele&lIgmV?xcM`6 zF=Ksq=~sA=Y@2xN{mXX1l0j}BPc}^4CKD$rWpx5n{(y1=ZVZ3>Dp()4(H&|^TD9!8 zj<&EFqx?hsz;4t;u;nhX$sMGscl0Xan+%~$hPUAeFDjSQh{h`)yQc*&3c^kfhe!_4 zK?Y$ALL7!oOaa!1`gFmhw_!>+xTH|7BZ^CN9(1Md3S#Bq=ys7otww3OWtbzXdBQAY z_$$iP!0XVgY_Lr5kdbHhaQp~zMc8hAv~u2Lzj>qO`n+XSf8O*jd92`S1OHCxnthJN6&(&xSRE6cS3;98iUW&!st@**yNJEq0eTA z`}S7MOSX=G|Ekjxk=B;*EB{^TGzQA=!Fd5qpYCm);nofXqSVh!bS8es%t*EDXEXTS znVuAd>Ld`NgLYD!axFzV=eTOj3mbEw0uk5xJ-tyLnkPU;s?QseuD`>RPBeyW;E?;C zl-%-t*w8IJlc4-bEHFJn18Jja%LS*68yx#@*+$DX!eu5*U3qtZGPinI9FWald7p7U z=0o0C?K<#+Px9~H(q(ledbekUzsj>;f1$T#f*}y=NYM05S=ncP0-nTIA&mwSvP7M4 zqB-ioYHAc;t9oPn$Y-hFK{9@!5P0mn?N5ixh!sUyY);s)NIbpQC-L+7a5@mD#j>>m zTY~im(-?$b>yn=v-j9|W4p+N2R81_XwN3))Q$}!4ua@0Jk!WIv0jUYSqW?lfj#0+3 zN%5rXC*$q?tUUzu_?m4Jb7p6?zsa!pjW_KdL7f)0jY*hyne)*n+?MrMkK-9B$Rpg3 zx=LNFL>r^dqS>>f)g5Ehr$GX?1j7xS!RwShQ!}B=UXY`Z+voyiNEmRINE_O~B0KAK zYMP87M-X;9xg@&Ceu;Z**C;Y)Yu!RZC|)lC!Leb???8UvB{ocXsy&N)V?G_*wep;4iI-VOwulgy(Nxa2K|Kmp@v5jrs9!eiI^b^+iDxa z{3AM~J9Kf8J^9ZxIh8XrY8VZ<8p7|nM@;}^0`|z1hPVyexWuSS2o@GI`rp1gsQjmx zggnbK};E9yXJtYKTK%Ee$fkt4;w zmB6Dd<`PsamKHlrY1pcWzbntf1q9qr2$@j*6B$=$=)<UD|-=y0T;a6 zjD{sEtKl%lD^c@XfRPa})?lG3QGdpGo29LQnRHQ1E&U#+eO$=o{Q3$MR13iiJwytu zsSxdaH_pvNzi;3y=v%9xQGc=DbTnM_-hn$ffyC=y?<`nE$95H9=zs?zUx8jg=oOmT zpVyf5DZLxP8c&-;_Vbs7JhoqHPd7*0V_4GBFcO%uJ^*D=rPU%@XzUeRAHW@}?Bn@u zVK2y-X<;x!(HUQ}9z@Kzd(I~opWyj5c8-acsEQw1uicjSN!$4l4rH-ti3E>wbYl+y zj^}N*h(O4){SvZdlu~#n(V|BHc?t5ZH2=VAx8w7=9%=Cv8_MyC*fKYH!&Z}U3eYxV78EN@`Z#_#Wr%NtWe)u>> zPj#hF>fH@>8ZGUfJj08omLK%eq_c_d8_K|!h+c7H#(FyC+9vfZvZJ}mt2Oji|H)LZ zh3_bM4*;Qxyq5?z=eqYQ`p#*TQ6U@bFMXt1sQzAJ#%SWp zZOfF+C2yCg|MFo)D{ICE3Q;#iS)m25R`deS;j4w#!}9_{nXZK;cI_u5Q}g!)O87X% zFv51r>$5%Z*M@`n%NnkGUQ`1`A?G2CO{-lZRi-uI9>CRyOOsw9%6PRO%ujn&OH#14 z|F3KooXq_Me?|{EGEl#LAV_{_vG4yf0fkJH1Hh*W(D43Re>38`jfb9a?>-5!c3$ho z)b$sf^qHybQRhKhHRB%6znH7oD1m)eYt{PW?QCZ|hz?`VQY>7q>EEkw$4I(3_Y&#q zQ#-Goh~$O~mYdcmU`)BOEnQd>9;70&veq;);GomiTtutpfT`%E`A#0IgesQxkKB8l z4{z@5jV3}s_Z}i3Zdd?ky$9B`)UvKu_5>oJ>$H9pKe=Md@s%b3dx9Uljt?O$O>9|t z4~wF##l_RFZ4K&=)iUEPC!fJMTjeVKK4pq?+0NCs#79Ey`C$GYCC2(4!e@CHoSNNQ zYt5zxR!uN9R7d2z%<=w4)kS@-$_|?U)5tw3_bs-UeFM_o$LIz{qlE3d`!%rAZdQFXvuhv!kKBoZo`XENo~N|z7D4&+6_hFH|% z+00X^5pBV|4j>4~O@715X8N>xFga^5>@wd{r#}-T&7M9bnP5ww_Y%oxfyCs`Pq;pq z6Ol6FbiciZ@|yKX1K7=s{A|%mvaZ`LD5LP{Y53l0RM zZM_*m0Wh^$Scqxy8vPVwWs92TL`Sns;Ifb5uL%I+(ml<@fz@{RjW-zfjWPrg`bNnFKU!=(v z!kLI2tsP;0QOTvEF6iB`NAa_4oV%u5Nk&fnW);3p(Ns4G%dP7$OK%Ir{%unh4>HFg<1#4alTQRJtMWw;y9mvIU!xz?Nx{V z-zyd6Ky1+XF3sKGcn+QASQ{U}gaxIt=6zw5D5zW$WlE5J0c=)|o~duwN;Cbhp1iSO zX0BXJz(nck>v6`DB$;<)jC&UW(Ca2CY%2?DT}^(#kZxj$D4)yZKQEjF+UP@lJbrT- z99`H0$WsCN2{XUlKb29*_Ys$S5`|?5a8vSiv|Q1fcyHm8+b8Q=zeOxxVaQ-ZTX$zg zUo#C&_+r-?>)NG^0p}P#bxIfkGUD7y@IAcUdPBXX zzpsXsyjbYf9&$uHS(1JKdVe{~_He?nWtihdP0~Ylu+_l5Lb^CA_;R;BxIseq+rSWF z*A3S#uF`zbbA8Qe!vFdri{%w=RDYi?P$tFFyFB=L*kpC8;Off9@=>0P^sE8F>p1ZN zwq`X{sJdf+Citp)Hl1F~zHG1_gN4dgl2Bw>EBfI#jM=Dr2LdI>DOw{!v)prBuqHYL ziCSAJfX?@=8AH<9NBGQXs^VQAt!4ES+BU%9{Cy!SBXOu#jM&oB?0hP}bhVgIt^&A` zT82tpB9dU^rEZ`T$T@;wKwaz!;O1v0=gQTGrHZ_ual(He^mi++AvS-Oh|OB5#wUG2 z6kXVsob91L2AC9Uq&Nzbf}7aCICP35m5TF3TNK;XJd#u^+ylljG4Z>0rhi6(^r!C( zvF54vl3P(k#C$FRDqCUt7pUOH#$tjOA>xhn05c z9!${U?36TX=i*99EZy*UrxB^5)v+D zE3p?2jp4-9Y&_-v&_`o^EmD`8>pumPug&;b7T#KfMJ-JSspbp=|E^67tjrHep%e#D zElG#IEpxO$!i)h&ZxvJBjpay{G{XW5u0R$cJORPbr*$MJs6F{X`E+6gbGeg6559}h zcxB*9`FD9X>x{asga^WY=gLvKTVs@~vMi2zK7!{;iL^j-=CWCg zz($ll&!t1kjYK!S+w*@RAG+a_vds;pJ`^Fyn$ziK6rP$CQ;QeaucCoa7=T?{gyV>9 z(Ai*vqyK#BOTX$VNVk0^7KP&z_ZMKu5s?>?jciN6IcZ^Lt3f0bRcmwtpJpP1WsUH= zDggfZxYu78?ZnF}0dAjq9VY^?-Qabuo27av%j#MY4GF$9%ucisW&b8Yr8_V(G}T!R z3i?30#QLn&eLNvKt(+ zN_Lz-JfXFy16?b^%`%YDfZzP`1Xycv-u8U1+r9?AIotUde9H+4hGVY~*HP_%@)&Cp zneVGJ{jM^n`SKiRB5WNbKX%E&*5p8d)u&SAyyW??P71k}s(FWgpY2PZPGL^(AC-Hg zk?wBvNj)K>{f(CTyZ_)Jl#33-&pTBYDA`NUiZKd-M^sSm!*aydcZsUw!$4rQ?VM5KQ+NN+m7J%T@sR)Uxt1lEFEG&k$OQB`%K6%Rbe$(tswHW&xxgruq7e zww_6%h)r{%fS^;Qez|u3{+cvW(YE_x|eD*h`osj2s-&1vX2c|+C?2M> z`T@emE6b*D{)7g49uUsJ1t)#2SmxcDBXQTjU07!7s{ z$wQl9}W#>pA@p91C zYcs+=$^}|Ub`z*pHf!K0g-5Pw9tmnfr4*U0A>}90EvNiq`3I{vYEgcKHER1Jx0Z;H zU`?3@52%VMRDAfIibfu-5N!KAh>lZT*uh&*>4;H=BR8-;SSc4nzcvcWGRqHsxZtc} zl*VqM&o$r*Z9EjpjX)H$Ea_iim7~>fla?*K@8fYOWTJ0UM;AU=ZGm^rc%XQIG0(vS zL5jac>;XUn`Tx${0@ruaZ!?;T!`p%Tr*kX+*F6@&S*ia+GvRm;$s*?KuWw1WhZiL9 z3nm|a*kOLs?iKM2bdp+tj&Mlh_V5%>qO5>#b87v~8XCx2q~vuEwO|kbgw>~{bL6?@ zH7X_P(%IUp67hbj^H(kIVbWeEx{Kmk6w&@i$z^m1(9L6tfR&Dcv9x&JDEa0Sc`lx* zaFLepwMcXps?yX(41{{yXMT157__*)phFTW%Z$_=P=R**OY_jQmK@#)l8ZAiK0tgh zWJfSX=l83-p@L<|wzYnGi~_?r=5oXuG!CU)@9o}yPT0_mLDZ)L%gq{)vrEkl&xF!@;5mTRR=?bE zK!GltP{iO2ov`&@BdIj?BqE!xnh{PzpREOG>S{a!X$-x2^CfQCfWQhvIv zqh3`t9r3G|ZIJHRhgV<`yJx2ZV|T=Eo~hI3{ecwo77VNc5mxfEm#HDY27+? zH93>m};L% zaNdS??DW8Qw36q+fjQF)@(VnmZPA+vYPkzyf%?Bjn+CE71p)1slsjm9fSA!84#%lr{$h=64UN>FWA+^ z{0ToyM5pzo-&!xr=goVax#OefH$ur{lkRubUCdmMUHmkxfjA*gU>m+J;X@^@{xzHG zA8*l{loYNUT5;bsU)1%@qrkZM&!h86XJi-KMoDKD9~d4!{R+3cL~2G}GN54u=5m)v zmg9}%rVWgFl+#VrX{^5OeN8+rLW{$KK9L$1R}~K_pMklFdJCco2K_c~AtXPBE`H)H z^vq%~k0SE>Q8GgXUMnd800h4QpD%7he*grPZKSgwG1OqQGUJ$f>vF}0$u1pYVd#|T zcy;O^1+SUZ%>UA%4aiTX!{>6YZiG10;j=di$q9ik!WDoB3P{DCRhN;s|APqA3Sd95 z7#)(#1EOgYZK6J6%{ZVbv^W4OA{CYNo5mb5tOaUmDaxhi=@_moUoR&uCTg=(+Z3?sAwB%?ya<8FF)|vfZ)F70&vpl zu|@shn{$da$7IPeNeU)l_**+;b3=SbLYERZ4FO)wsd*mxgFAyC9Tg*_YGe<(B(6!G1@4igPtDcKHP}3v;@6|e^xyJlm$@6!ak*%qFfM& zQ#W~f287efk{UQGJ1{cdF!d$jSi5B6O9C$W_V*0{8Yw;s*w=%!ov&r`Qa>SI=(t*Uymz29l)?O-p+mHmtm>J@g_vUr0c1z#&|KGbng7eO9 zPjQ_lJ6{S7=2!3T^#Q#R{*)(8D(FS#jJa!8*|nfc^4?9dA2j$05J!*%VGp6$^~@U| zdK0wAE{SEi{Hdaf_NvY@-@PVqq2-0cW-g|5L#>2&o!*oA3V;HVb*T0aW!kij*6p1y zD%IaPehuPeFQiDb>qz!$-=dP~gI8{1t?U>)d&sd5`R5j8UC3m%P3WOxnhfK@w-^b- zG&^vK?qo|}4-u;ih$t?fBcpVlD5vY<4ZfNh9WLU@@ja|T5(yWoS9Dwb){*Ingm^p4 zaz$=_z~%V+c{tyPgk#>)%#*XRAU9l`t__uCPQ!57viTW0Cm+oPWww%CVexCA4Ex5^AA-Gyw9=$9`ob7!Sr2=Gf;e~Jj9?%P_)XK~CPHpn^G~($b=A`n`Shk4 z!JUPJv%>lCK^21QCGG&2sF5|4cs6e&$mQO3&oQW#I#OF>Pxskzl&m+Q(!6lOV-`_> zjb@%*K8Djz(0VXzvSMJc2TM2xY^jNR-}SqWi90A&7y7(W%8=p*kCWi;U^2DOUz-06 z=bZZNRpRwkm?@Z4;D_jOPp%Tl3-|Zjt-f~HCwi=_D~}>rBpgGmd;FYdm2kI{E4DD( zLn;J7{!*%*So(}b!${u9g1D&MXkWb(!)*0Lf$1qE)sbr$*gzC2kI@dnqSCqHz|!@D zZV{B5a{NjfUwTO97CoKV`^rH)&;JMXWts35+VyqpQ_2YDILH7180bNpG&KkXvEu1%p<<8sUm7Dbh98al48a3lYG?h&l2nS5? zweczAvmsTExE6D-ETVeJFlSTkhBnZBUfCx3sB7#O+Q6wT@|U^A<4z|r@?#IhM(@Tn zp2y=)ZGm}Y=yA2%U89bTg}TTLh#!88(p(S&S=Ti$*=-LHQg#lbp3caD&9Tm9mU6G< z4RYI*r%X_0!Ow*o^h`!rr$wf0C)mtomU4-TKUuc`8N-M+B;dW0Gkgku=lA`AD-9#D)ov*UIDi#gB(=k+fO6>%Y+2e+Gi$UH~zU(>@4J zG5aX4zv{oM7-OTBM65c=ryLGnS*wc>Q zYXTW*ZQuL-Ta)T8ICep`*hWLP@Xv-kMAxa4*34g*H zU=I=gB$_+mp=GO>j$6*P84X{vcM-8$pQ~5gf22NU^`4NS-%2bJ>e5ok4uLTtw-suE z@z#+KkqbT^$3&o`IA@0Z)8O$@eZQxR_s19yHcj9W=Wm*EOdvV;M9@6)bKU0|_lr(( z+CR9eh9TT`ZsIAVMHwh(tFxgASp5C}0U?Gx7E`IFKQ}dXR#;Ixe$&|m{6rzh+AlDijhQBgn{#RwCQxz zmN@Bg4(woe7Wf}Adf>j)Uxjd5Xnsv8U;rl|hJ!n0{`b@9>z?8hie_wf5;-oX7il`z z1;!9Ei4XWlX9fatKwklF`awzHheFSxpiV1$#~jR@VBN=Kh6>H0W@5HTizKHQQ{(7J zIEbu=c2Qwd$jdpQ1X#!M9K<2sm#?+HSQU=IAEKgie2Vu@;f_|_tQph9oOsPMvbmDad>>9>^Gc-eOjyuP5`3>aeya#JXP zVnQOnn2YtpC(TkmEr_tkRprYOb4k5xQ$NKHZ92|OdVRe+cobJIE16&=5l~jrC`b1v2o5B1roPWtkz^%V?*=YXsW=-!M)G!q{|t-|G>eB{CZ0Ed%XSyh5mFcu#)rZY&sC5rK`1{_u=i2^v*6;uA~Jj%29Lp zPe1b^@+PQzseq?4bDTAROV~0ZkH<)+G7jx`Iwu8xP3Y@)=caqq0y;Wtc0q}+Q3W(U zTfgy{8O?>jJZWE#J@;0Irb(tNWoWMn0I_aQvfs{%beqs2 z5bLhuXQ^8HyoaSH@hnzKD_PxbFUV+-GfTR+CK(lHYIr#|48#nuBy70q^$jd1jjL&M z5Z~z4=Dd|J8Py)Hcs{m*ImL17)73Dcms^sZ%}Tl3{%<4Hwq5pt-*HHgU8><&KA`(o zv23Na3Q#>l7A%UFDYD;>pFj(`vY0oFB|x+_6EfEVaw=neDcB*}Gg_kdgaHW9{}v6+ z-axFcWg%fY`;HrYCfhAtUMczLhe%~PKl!2ih~qU0PQ__W7xTp!r8!o}p}rqG~Q3sw;Wl?78^q%-)$i{d7*5gjb2wW<3u(h)kuoMGvw8<8y@1u zg;;(-M_PpVyf^Q!yKF9$9?LD{x`+4)eES+Wwk95tN)NY5n9O*d(SXDjSIPlguRf;A zCPMW=%}jW|oxlIvGImsXEE*1ZbU)zgr-saJ|| zKFl+dVzS7T@Rv|YN(*w=IbAc*xNH{xf1od@_6sZDZ?e-3uPKWJV(P;^n0Z*)8RTHR zFu>J%6I%@Mko*1f$}=C$&zuO}pK6aZcj=_Q_|*(ZpOqaeMBQLgyph^V0y->)xtHt4 zf=1-pwi@Sp?@A&&U~MaG>)*}QtJkG6D;m+kBPVzNVI`8jxvCqJ#7*t^#QWZ@vPXcW z++k}~YRX9mh5WI945>6s{N{QevVcfQg(yZe;&xN!PT=_7lb95aqoYCQ)cDVD+!fNk zWi4{V5pMwu*ZA%Oc$|ium7zM@vZzxG)D#jXicx#Cjm{xRm5f7^4(%LC%CaUq5q%cf z?`H+FUMK>`_ST?E=x&GQb31AX_O8 zg;ycW>6HuqcNDnF+sJAGA3NM(zp`1fX$-!cB>t%YieTCPF!lSyB{=#VFp@A5PG?8o zS+7}WTTZgJzz~W&K=Jazmc~JH(NFVOFJI@>e=JIzGIjoK#Fk6Xep{3TC}Z78%`mA| zyR=*d95{5J;2Vtuim(rs>V>Z|8D`!sy?~o@DFB;$wZH5Fl;WkoG?0q6*XCe)taafe zzdPDM+^#4e%^6@Q=km{GSPpa;O7af2x$uVB4}8X6V!1Uy!+)&Vm3A?(LebV9W;Pe6 zvha=b9;cvi4(L*^2JorD7{H?{%b7ztY=U&BowMpZuVD(qDmlBYS$Q(mE5RoJ7bP`& ztxHSD-6#3d5v%t1c6TYs&W?d5)^o5yin#jp0$lgFW^Q$R{C7V317du#KqTg#1G8{~ zYKfpX3wSdxB=c^C1&ZO1S1Qc@6_$S}`X`C9StVeLfBB`wm)H1yHDQP4-gpZbps=EV zr-g6*LI%nPfvJg$dX#WE4HEnFHWCs1#iBToy6YRdBHV1qhQEKGvBnQGO(md{#K0<3 zy!qx$PMP`H0f%~DZ`bKcP$tD zcZA0WVW96jf*7o76PyjnYFq~=l0tAK9WFy(`q#253(@Wh;raiFybLA7h*LGi^>rn9 z0jn&qVh7UJ)sU1`>u6^|e_xSl*9c-$AbjMjphbQh`Np$@cNQO^3jNJk==gr63AcgY z?S>kKYlTR&Oh6%oL<^4-Aj;RF{f%S5U`*$McJ_RbDFn3v7>nCLQ^R{*t{7Zs;SHTE zSo8ZEkzkIR-{ED|UY`9s?0tt@Q)AX1A^~dJxx+o!9T55QCSK{%zn#r`^4XYl`Th~O z=Ux!!o~=GgC*Ig>wvox+1WL!{CO0wwG&(H5f$wPUxAHadZ6Ujv*{G}zy2E~*M*Tkd zs39Gaxqo^NKGscq|G~|R zjaReIazrb850IDU{H|KGn8|AW+HZ-O5gx)iu`0|n!5R5!&V2C@FmB!@fTm?wW$6P} z(VBLXz3qj8WZVuVcawUZhl>1@NlSDSWg_2F&6c$<$M%SL4j6}P;ey_K4-5ase!MF< zF8$NoEESorn#RyB2Vty1J>@Inw&0qL6v`;I&tO^yn4o9C4|emrX0HGvoS<3wWyo52 z_{w-}(Mq+zvU;YOq8XDYfXaXXL3QY_)iVMY@m=2N6yJ2ElskxUFU6F{D~bD77PBi= zL?KXNw1EjzSok$1jOc58iW-2I3^eeXjA?G2fTiINV~#EZ0smF=b54;gYHd&0W@V}; z%>w^0aiDEiz*&#ncQve0ryzA!`n43gj3CQ2yCmP*Nczrklx6p)OSQ;g&;msA zVJRfC^AphWf$X);_LfF8>BoB%5456mMgp7PT5R2vQB?xq$@(LCL+6~zwXjODV&R^r z3WH5I|H|(qTA>>Y@n?V3)hbHCJW4L=B$}&zqGx zE=&cFwULl!qB5;By!R12%hulVW*;?-qcRlBT;%9++863TjWUI*xO{K}icSoePh3mv zuokc~4BuA-#;}Yy+MyCW`OoFET=d((#xe~iOvsW{`$(`^4%4g8G-OL@E6^zksXrN> zz+SzCOm5X-B(=G==Vy_&h2UR#-`F5kx4Yq7e@>Qn<0uS#@K>MnLk{-6H*}$g7rHr3 zLL<0U^>g8L9jNowmmx&pgG@4WjQ1>iYWmKy6!>BSJjluYWU!_3sfd1lWLfDoRbG>D zi`dLi#@m5Vu5K23Hv7eNFgmuA8*1?Xt;Sb7RNiQp#-taU%rtYiKqsiiH3)o?P!gp3=n|Md@z%-U+k^ZBTV^~gbQny6Iw(5xyRf54swj%o4pu%XO-5C`bnn<*5z2ok{iqY zW`NU>hc7zz~jT%^E$9e2f@)A5c z@PvH?gW=r;d{&KmE;wpbg1AH!^3$*L74`-5I&t6GMMH<#qwDzSqZl_oZezqhQjo#5!@-UT4Q&o_?z`Ps=FAs3Al_B^eH?Q-0{l72S#PE=??|mK zBBY@%;xSeyrwrAwFhI_D5byBnTh*9=LDm??Q~+s2SPixOv4Y4(KFTPX@&Mt!f@dG= z%;u4>&QE0bJVdHb)J4e_ZzSKGz~M*_^I0SG|B`r}&Tsr_!O|yQNfRE=0{j`JHNfB; zjTX$uFD4KHGLOh7wxFpV*(Ytek(t?7Oon%61u}p(R|`dh;pDAZ>sum!v5wW}%Re@^ zZ|{l>hc!&YJ|<$p$PUt2F8gFwAg4M;(b7PUC6fG_gXgN`B+Km6R7X19{gCu2BI^S4 zfe`6C3S){tl7IK(U#Ud_-+uffOcFg zDa-yd`&{pIA`(n&yIzgdyfd+vgNxnE)A#aEzxKCUE7rZR=Q3>UgT|a=>i+d$+&XH&d0&?9q%v0&&WnvsrUpusur3R%=eFfJ;xgM87RgBAK+PKSt- zd$?cwPAcS~ zNhB9h3kSNmALjX62>1fw&o`-Zw_E6FMd>U1s6h*z98cy9k$cCBhpe@T%XCF)oIJUJ z0reG14);+s8VMCElHyY2Z9^rQ?a^O9Iyv2CnqX{~W{2Z4m?E3jlh3QKc@X_eAqwSA=ifO$~Dph)eo8`6SYSq~= z^dOTArUEMgK90;q&aFiY-QxdFEDASg0H*1c94Nquc+;YJ}6AYS+mp z$q!VV0$Hu*bn%b;C3r;WUZdjj;emzFoytJ{>uhP>}4_SD6xE!L? zk9^a?f3@Wum$HHa?~&>Up~HL1Y)%NWoRFtW{w?NwBAZKLDj+&E?AcDQw>qx&ta`v2 zZNLImUrkQ6{X?+(NAl#kSw==^6nUKU8|kq$#_|ZM$u85 zWIez7In}U-ifn~HQ zbAVQj+K}?Wenf3B<3#cIvE8SlE__d813al(rvhe0KE!CJRsHH%Yz4I94vt(K)ZqHV z26x+s{jLOosx#nfFVfx&^2WG{NOnlRTP{T{72<@Xr}pU~zE4Jq^xMC!-{#|YQGq?l zOH{oSG3U})aft-KyZ^ue>kd4r`G!Q(xs`8P0AtT5D7=4pDZPNvz>&EsRyxT7Jylg# za@l<|xJdzi-aFl9<3brwG4@L)Y;et%GBd{#9HU@psdhS7J5M*d?H8jWvd=>XuK960 zR5nTVdSo*P1cPOKo|lZp)B9`IgQfrg1N1?kQY4f_Ts!{&1<&ab98p(xZCU^#QH1jB z#j=q!auv~-IY9fLt0Q9)%24gVN(6_g3Al8a03OT*>OWfrF~d{i!O8!IrhkenFV2hu z+~yCn8M(%r#R{(gdcSiQW}8N%f*Sb*aDU91t2`ehhdKXX?meHn8bh_wjEnHHW?>!} zkEqDb2rU%J#81YHG1&|Tf2{dxL(?Zy^9yyqLnhE1cfaEDw|D^i$rHPP$_^zH;&A2B z7J8sNSJ$+dnYB_&@-3E1YhAJaIpQ21LMS7EMPJg_$c7PFV}4=fp)u_~^P&=2mCK4Y z$`BU!y?+L&Ib;f@*0m?Zn>KzbWVDv9XVW6SKIocXSaISyn=&0ljs6tGqo{?T=5K_< zr+5+?WKg^sEr%^I!2V)mtCGo*r7QL`20dBP@-LnL+uzPImZkXu#}$u+q5x|^l)teR zTb+kk2!-|0-}k!~iG!tk*(+`jC5k1CGa)nf#A&dVF9MXwCgP|z>{&!TRgVp!0OJ~E z&jcbqp2(Nm+ho}7)FGdTai(>W-(|NF@KUh4JrEJ^^;aWeBbr@fro>H+D$M@~z6-F| zu1By?bR~^}C*{A>?(xEFqNS28WkFURL6+%Go~-ucQ)ejtR2Mn(F7c70&{f{{#Mrf& zdUIXW=lM+d5J=R2kWpDv5d6L!0wZE!D?d_1Wyr`B>l4dc-q~Wii}xE*opp{e+>Vit zbgX2CNqnAXRu<*%Ld$@$uPD!DsAda@^KJjFxOc{szVcsjhIT!-PQR4)KNqMR9+rwP z@p`C}q*&`^5akIOnUrP^OZWB4o~CDU%4z^!%X48^iWa2DT5Z1N4Z9oKbm}jHf+H(? zm@35YLN~=rVn5PKD!U-Hjq%RL$dE8Bj zXILeqn@t^C!Z)o3!uZL&S2T%C!q$MwA*lkbJV@}xk;J#%nBMzEyorlt&J{zGkoSdm zmY40P0<|!j5jd!SkPoYKg)Jah!?b|squ5?`)@%?kdh=#Q%dlahvjt$7kSP3&S)q;N z|L!3G004UdpK&P=-v9*E>MUT3`2J8RIvF_e%`0|D2U)_fAagx}yCKc>n#N2LJ=I(> zm2dqr&`lmnqeFJisQVPpqi>1c{Cav*2$}$+IN0LhaZl>vlVuY&of8Sw(2+O7pJgOi zXHh3_S?M;9MQbuixolUULysi%qlcm(SHJ)O1JnVZb8bU_01FS#-EpeCIR71-I|gt# z6YpXl-LjkjO3c1N8JDGs5yt_Vq%ZWojNt->*zUS|oORj;Ej_Vc7@*&tTw0I7IM^*a z;H=&>?XWUy?X3%`_(=%vVI+JRTDQ?dH-m1EJh|wPoTLVg-+4Z`v~4eY^^<2K=%=Zk z^B42-mt2J2K4%t>PlajopA8RaJ9)>#)PWN16Ix6ebyWt)`0=QyEAl2*?yOzfL5)FY zXms5z4sRLC1g|q?iS(WYW?hQF%JWO8q9AAc!Xwm$eBO%pR{QI$<;6@$GN(VwXGrD4 z?`uQ$Fk?q##soA4i>MIjmEB1P&<~WkJL9gTd@wKBJP1DN39=nhdDhp%Tr)@3YVk=L z>idPe#@`);-~guwP``F4B}=w)lX+72+nDaql|oeNI&W``-W6p2w6w%W#`^$e{y(S* zu`1QljCoao6Av<-RbAt(8k)y8%Gu7)4huk)sOnCsj&5zd3(bH{#$M|DbbhCfCs+)~ zn94opHbCDb7DoodqEzAJgZ4h+r=%F%b=JJJd|C~U>7C5{_*)e27+})fM424vgvE8= zW0_EoGSm>8jfe_Lz4n=KV(hV8ffV03&&U)ALtVQ0Gx4D(h{4vY3D&@xkr? z)td}NlYdkTo@*!T?|{KZEp$n(cR$^LX|)U>w5jwtEj8u+GM3)RIiv&8*p4Ym>s5og zl6P>(3UPjCIumqpBZruIr_;S7B3<0d{3PzozEoMw(t2^^mV0 z9|bJfQ@VoXgUdSP0QFE5p(W|q_HrCy=mA2e9Fo7QjA1R{y81ci@5EzUKNK&mU_DW{WaarZ;8#8;aice~> zDcQ7M99}i`tRepM{kMejZ_^dne~8ps3CA;GvR6BXgk#F zrheidvVYm;|I{j$32;WKQ5*@ASJ=_udr?!io=*@LZ2#qXy2}C65wEA=#Kx#{M)pi2 zVRFeR$Q3`yhj0#kqd5iw=M8BML*`I)Y=28a`QeTFr>Kk88dR&?b9%-%d_1- z`MYLpexOW5D;$H2BEuFA#+%=;f`FM;v(nG)#_Wy9clk?Ht!tuX{b3RGiv&K3fnHM6NOB~t=?;5{U;35@nLAqO_u8j5`(iCi-hcgKlAr6df zs2~OQ)v?oePyboA3fYGu|F8#-;ztcVKVEbPLj#22jgJl8T0eyl>7Ua{2xuCLyLswF z<678072;_7uiJ>=yi9Ppq#tgnsTn=Fz&s81=I&cSHmQ?ZskJYsjiisO1uT*R&vP?A zq(>^)k`U8l-sElcvzm2iCd(>T2|M{ZK)jTUPfOO~NDXO1?<)4WyS#C3NY-29 zigqfXfqE%ZC%weNd!@gyEmlLTdkLMCwHry&pp%q6UlXLl#V%>mH3Fs2@t*R;_Be=DF(9<@Z|;!mO=)k zVvM9lQvTpm@fxTVSd1@OU^YSeK=+UOU1`PRNA{m+Uz}ju7bb_>Uxrt5j3+tFq;caH zkn?5EnZ+9yCt;!Q=eXxFBTOae1P%>%zPVHDgRR+CKADr80hh-U0vF>$v(qC%+*@T#OoWUc1=!6EB0N=!ko}#T7 z9&F-1F^3WTmaW<|)cTrt%yMs(DzDW zF?~J6sZsKb{@T+ej9rG>9$&flrN{;7*{A}xQU-8D}cV`7?jQ-UKkpJ)K>*}SnURdhKJ!q@5HR;oqpN?OxOQs_yy|+ zK3fg3ot5WR%AJUfbo2qO)f^grdnuAXL_?96{aPW}LFPqEkqMAUl8f+gsrK>(BWa%( z6!Uo>_*IHPPbxA~Pfa8MP!={tlV`fnmnAJPe@!A{BtU!ED;b`ekx*EL9t#GA^Clc0 zYzhb;hX0IhXZ%46S zj6!W7j%|8f9vx*Z>=QVE78l8;_LS2vx*wnSCz=HP$WYs=vtv{0{U-mRyOXbt;??7! zS3AM(7-+_0N0I-Y1I8&8x11 z{C+u^nPpqA8Kj#3EF{IQ{Qq=e-AL;I*q@b-bf}dF>tPq$>*8bn^j}W<&;?!H2${ki zwKzEyuVXIn4H;a)kJd=OB&M-X%zFDZ%S`lY=6r(id_s?Y=OfMA!*uL`f0FBEq0l5| zo^F5tu@RB+Nnm$v{~RH0yRH=lF40Q<^;jr`j)QA2>7?a1ITu1vb0D!|mQG;sGm$Bg zBDYwYrffQ?EORIP*UDD}Ok8&`1rLOrkXP5GVy52b#dza8*b@t zK9@rfr>^iH0k%TZ#2|t=K@CuhLf~HgQJ{nAujC>R=rY*EJ9u4|2$*7HlSH5s)z{XB zmh3>PU|+qoLJ{h#^elqIFBuEkLwm9VhhL3ux6t1ggAzOB{ef(;=8=%mp1&~Me6xNW z5VF%lIV+>d&Jg_yG8{29puM|v8bXhm07g?tpQ2ut(0IRZ6NH2Q zz&(*{ft5K5HW8o>e*9AI^Y?Uvk49n^i!A#Tx-2@rTL9P?>i9(T;ZG(ie9YY!6P)N+eQ+;%Heu> zWF_p--Kql|aHdJ^bD$MD7ToYs4otv_y^=w@lqPG43iZl9Ilu7h3(i=R?tWi5iWb0SEZunu#qNiKZ?3N2xjkb;|7 z|81to?Gjm6YD*)zD(XrxM97$yhj-yUxKC&nc5{?Nl+kQPN2eEfi#z9U zGyn%90PDAMO5$=Pz3ntAKo0leF|PE!7?v2WJo*BILnmPLlmVj=vity-{BJ5_GD(Kw ztyIobDA!03Wc};29f}RmCL2E&U}V`lrS3|hw0i{&dHMl(d9hp^fZw1FcNZx19^3b)&(G?>-P9$Hbn0=e+9zk-e zDlU2mcXc4&+Q+HC3?fep-*dn_28Fdp?v?3#UV6xw4My*>bY7u6GS$i~;>&Pj0R8EA;t4({An3 z3N8rRYwG_uHPHF`1lWPa<^Y$jJ5Q8t4)fAlkwv&%&fJ;~OtcpWoTQ_fiT(c8T97ll1Y(J! zt#j;{CKuC}=73~~wWA~A2Q)wKIsbLYT4RX)$$9-^4JWcsctgjRIa<-;^1?6^_)XA& zumwrKA}-Q4f;%8D7nTs5YKv{4grijPMY{${_hraQRE8lH^Q4#IGz@ORwZXHD`z`Lw z01a=7+=!8%iG1<81;JiDy$C(p4?~MukavqdWjx|!*$w`lrFZU=(P0I7 zC(*0iD|HUH*bAF%6r8U`7ZfuRO1fWrV}9z+7ioNA?Xd52C-R^Igh#vboi_7*q<6|6 z$AV6jBW_}ET@z888NX;9>uGVE(Re$R&y zIR|MNlbisfzBrr2IENK$ZOZ30)KQvQrwoX!UoVM+)Vn7N&}!2dsV}N zHh_soDT4k?&E+Qk0nHnS3!;GI)u(X0<7E}!)Qbd}?GQ{}l=^MLzM?f-Xlx3OwG+cwUe>)@FiD}Oi8NF-7Y~<#X`|%Pw?PhuC z9u>$G~@qkqa zftTK%<5G@zA`%tX64M<}%jrg9peH!W${h|2KxiM3zj^b)?KNh_jlr+aj}#2KI&gCw z-NzK1Du^DqZ$O(pQ6UVeJ%TiUNH9!(N}Y+a8QhXUiPfYU7uuDPLtxM?>$%X|A62Xk zwbAZjeM*0joupgF_K_Ti!&tTfEe~;k0c@|h2qKD(m~^8GU-H>k2$A;R3MO|3_FpW$ zvg4CHf_hq56y%o^%JXiPSU5_^n84~92)6%&0V!LJ;@K)w_>$l{bbKs!R>{)>3!jL( z4vHswqr|T(llD#Z&FJXFKwS9=w$SG~Yx^g7U9hqs*-MiXejhhKD=Ap{=*o?2m3bf z#>CulAtN!G=tF~I=fI=ImKLBuTA1W8L!2*@ZZ=Ky(N+9ogQYXOA$|yS554}iYdsA1 zFt8tX)4jqO4AhBxI5v{n&Xj04G3~I$Fao{!_@@vZKJs=FKnIIVF~%lIJUP*##ZWnP znKLPAia5P2q9ovf>aKSS=d|6Jr^jztG;!vx;`(BS%k5+G7xnofpBL|HuN*~c1mt2E zB`!7?`j^1`zB&!Sg0uV-b~}b1UF0o^twL}Tr=09%!Lg{8n9mr4Ff*=hIp?@Gh-Xql zO{yiYOUo#ZAa{uyczLi`an96C{4Rdnk$W4!v?YRkp6!Zi;;%u857`C79})X&$!?Gi z*%`@+fn&=nL0uirEM)l?qv&0f+s8T~gLYKc;(T;mWhviEoV@)?*97k{(K(y?`#Q}X zxy>FA!aZ?EJ-Q94h_)Qy$LR9yR-;f`;ptcp5UyZN*m`=!w5hri0C0$6ZHoTkqU=Kn z?Yn`Tdjz|>Ra=pJ6*F6#gkKNEh_O5z{FS|IZ8Si+4s%56np2YqDPf5nHZWruL%08R zqEOqN=CWd)iI__?Z>vCz6M#Z_!`Vw*}EwvH>tM zP80rYHP!@R9on?W;^~Ugow%zfkJ8sVu>6+~(`X~X^USq*itbF}EfI=m1eEg@Z?PpD z=pd4A`mo2WP&(KWre);`)Dvw}M$IqUyB96EA*6vtwn~X%lFNDJi&r&i`Bnz81_giR z!FBFyHZiVH2v6W3Z+>6Z9?iRm*}6Z(rPTvpj$8{^<;nrST(IPV=ofLuA_3|v9#F^W zQ8yU}Tjn|sW3N|PrPvH^a;o=4W-rlIl}a?xC)x&mZi%f)5fAqA=>epNA$*5g3lkSq z9ghS~AqNa@F)4W1<2hq1d-n@WMV}5mQ|aZj`WoVPqC`t`WXZrf!$w+(NXuHsZbMU3 ztxysXWgg{KSh@@I_vsj&>03$}0|>|{x-c6a=qyE6uf&57=_*)8s?3vH23y#FN+t}N zP6M%AFuHw4!H1dq6FZXp=n(IRaK2d8>NV&KZ5cKZFe&kCfmvJeUswk2OH5Ngvsu&H z52}DVNU8=IGgcH9550~(EI$pn7@s;YXAIhiEs$HppBk3OIKy{cs9&*NE! z&G3F;)Pbzxn>AV4zb}sZd6X>X*%~(;d3Sh_BpGrE9oa9#jIBP-SMU!LN#*)*467Og zj;QdTf_ubV;seh$V`U0kX+KD&TPkZea_R+>eE0sgJ(k!sDZgNf<0c{kVOHGo$3JX6 z1x9-Z+LlCg?)P%3IMU>QFHlL*hk!>kKyxON)k+Y?SY-UU4qk`#93NqH$CnGwQ=F2n z-)jusKY^y9iU0Id`HI z%?}o#;kk+_Ud4@ay)Z9Ru**DOHAVSrJ;~GH6VKIsIpPHb<&cjvg6E_->a=G-381N3 z2b%kPq;@vyzOGV`RNb;Q6u#Xbm|iUR;MyqG+|?|kgHrFJ(I4tN*lCD0@%ylagBDT^ zPn}eD2AkqNh(H&{br9R`e+8e03H?2(13cZhwwT~O8Bpdk-KP~oH391b9jv1WIEsJ& znUBYw@&02;4zS1zehD`I-`rbE#Vtp;A0sn<{h$*?42LJ?@DE}bc7)a`ro9vl+woIC zON8rUk)ZOVsx&?E@tMD)vG-bz*h+*9m;%ejB*&Jh3yJMkA zGwUM<#=URgvg3!;?)m0@gO(EncPXl{54bV-?o@dixhfoeyg=U!D67t^p7)&sf1Xjs z#(hpqw8rZWA;pi??0z0y-pL@tgIBTZ#Hk=w>LkLOvIx}7NF!!cKLw)X{=6*nDhryL zdWr3inGvL3PW`Z*4Dr+kAAbo6qVLD=O?FJ2x_(*VEEvHTTf04?g#Ge3W{Y<^`n@RD1%94R`?x03>)$}%%Pw|1=E1Bb_FRWJ|^iC6xnM)+1D zcpsq#@Rjo^HZjOg<5n8WOg@}6FL%o~D7zB#nm1*ETYG-4R>cxiyiy41q70c03V&FS z{cZ6GECzXeVRXI%MGC1koQ7mXLqMITKy@BOuhrT1>~2$ZGE7d$LY%RZh|MU8_!a0b zQ4o}L`Ej90lmmY9O!429N+Y?VQq4vx6pBlr0>TbkEqfr?oZxwb5kHtbDCDRB?>*n~ z{)!B;p)}NB)sJ<|di50%D$P*t`|k(U#aaDjb^ux=qqClH8<>v>QQ$1SE@M<}=WL(v zc2I&A5Fl$iVaf+m-2@Y`W7Y)O9ei?(k?DZW`C)o~!sLtor0g+B9WZG8t0U|sg_g}Y zXA7k`W!fv&yaIe(LxhK34aDi3R<$hoy;DsMdU{sE zoRn5FMpQSmqFXX;>nQ+h_$~h z^SlQRzur)_?|DikQ&8#$0B4XR78CcgM(3yK_dDdXb`1J^Q^LS-1M*>{yfdGfg_T&a z?XU+bTSaTP#6>0^!hVHhk}BA@xUTwF)o7@pN62aa4T4oMT5CUBdTZrC(}p3pvVS1& zX|`>rj?1?u-GV8%j!vkRkFC}Mk6j(DDx5k>2W+m$(7Nj9>CKb(O+OF-00EBypS5Wa z-vAEP{bOQgJdI*kK});*V)%#fEr1xyAhU^@I#}w!bN2T!ZsL<~51};UDn?af0-2&V zliw6rcyQy}34threSjN*cnY4`ZLt<0-zogBGzfb-V|E|gJ}=B{7j~;3^U5E5`jJ5& z^5C8VT-syrLuRXR`!M$Qx)A4iF`(3NqjjGzG^a4eBp2T9C^-I>)t-^~(=`8MXaPz8 zRr+ zsMyFU#B~hpjPddNW$;{_4pFR^SB+jT2N$Rijl&e;Kh@J~w+u??z8ktR1J*F-X{luN z^Lc!sn9+Puf|szz^}pAeZP-j#8J8Cjl60vUq=5hc0tNw}w{Am!01njm3Li><04=~+ z8!XdnrbGH{?~lEAfAY=jK+^C7KzUAYRN6Y#uBeb68(8zG?w_zd`mqqY<4gWiD>gkF zvzA^9=zaxD&=HvY%L!zZgu;k?T*Q1*C&$1b@$dwD6+%Vcq+!l?yqp9AQ_GbC&h(JB zsWmc(EWAB_GCsMQ*keeh9M&$(OG+-Fo*Ju=v{7Q@*)AH?1I6W;Xn|oay_~fjCtcoA zPGasbkR6m4?yM-6XU;y(P^?;Hr!?_7rk|B9dYQ)@IHxP#wqevGR%T+FJ42!upus2) z+v;?nLx8j$Jttq|J+))nnA7<3QSznP+iGOU?xgYx(-I3X*MZRO^sf7q$1_uqUPyZ! zCBw132i2h$o>C&Qy%#%%&uR9)FD{BEWHmggl!coR3dGam1RAQGn6-%1ti5nSN7dhay9$&#+_1|DH^MGZ_xz(`p-)&po4=uwWtvn_ zyIyoaUa&^em2T|ODsz9lqWMDE!+(&zC;^{|oh z_Rn*=C8Uau)yf8RgdJ-{q4k#w`8T4da?;w-BE!Dct&VqS5qBwe&gJ5Jd{&@%M@&Et z)(8Y>sR8D4a3O}H7vSKVVhH%Y5bMSFt6|x9%4$Vr001E~L7Tia2ra2Hm;@33{??4J z0gB#;fEr?!GSLN{P<%3l@*X`TL@lsls>GJ3Ue9g4iG1X>C+{3F^g9kn=4o`%_+_&g zM_SU^uU3*&h4~$})8LA49v95zVJ(0>!lJZWf0K<`)6!hjSJR4}x0PZ`Wa6qJh==I? z>LMAw^t*v7Cw8!R>G&OFH`4c`il_ZyUGi&b>|VCYq^%dsFxO6gT|%D0sEmdb{H_Ws zDnH?0mkCZj`JaB+gTaU`13sMF?ZkAVX)NACZnN^SH z>9?W(fFBO~6Uk_y+o>fRPMnbTyiaq{%yZI@U@)f6e(z3laVhIaoyN)~ELV-?8$Tov zg_n;!M6s_vAoseGpjJ73r~>G&>O{l8R_smSXbM?*l=5j`6%9A}EBXfHpINk*AgAckr#mCM9zt{Z6b^V3^%d3LWAMX;bVGX z0AVGg@Meg$pLEVqIB0Lch-0OaUUEa)ndJO3$*7I5##IK}Q>>DzYh58R(!B}W!hM<* zS#%&Y83-F%aI_se@!_(%Q6;&og4D2%EAxhoJ8@GjXW*grfz!bG8cp~`RU4GKbc3S) zdP3#l{y=6(+&XiBkHEk3YM$mM2^NZj7nhU|w zCBc$tkT1TGk$Zl0!{39$KfVo-)*RCvnNZJZs5aYz*c}|8%~X`WqhzWLuWKu4>;%K*E;Y0 zu{EYpGseH{WspK%#zF3l#fT;fNl=}0e(oc4&tsE7Zyf0PWE$?o8M2@AJMsaJK)ANq zTPan#rkm`GCT`2tfE84h(l9t@)mvV25e}%W7Q3kQI?OOaPY49(;ay0?lY#ZUf1o zxNSQ@AF1Q;O^r5txL7yL+C;Dk=S2vUA6&*Tv9+!1`RcqK{ksyde_eY6%ZL?VaVzx8 zYU39tGx!2lfUOLnKAkg^`32aDtH+Fh4=XYx;b_g+w_o-7gs-FWNO{mFT;a8^jrPNS zK!3zU4X%BD^|`2yVXZ*Ujyd``;#aR#Tp*IX=+G0SWi{IoB($Hk-!C$fWey$~#WG`+ zVAvt(P)4){n@(t6K@u*1&c@=?;(}oFVuMJw9TU~D0o!@co{M>SXvHWEFz|7)s0pIva?0_H;_cJJ)QB> ziIx`}3~jd6u7H|!Y1haj_r1gwNVX{w0jfHVmav5|Nf!lh3fMyu_}N3Kh3H&eV)wZ2a<~4#{0hu7%0S<`4VrIV%8Y0)i(Mk z`6;S=hzI>!3wR+}65TaDUs3@2~&?%*)Kc&e{H~N zI6Ww`Ad;hVEzc3+clgF0sdH#JxDfj~3s8K;N^eW}Sb(36j+~y=y+upZ+A0C`&!7$o z7R*K75+Gp=had8#TC0$K{0G?OOG{|AI}<{rh>tIK^;kj-V`g0?g#i7Q4R^(wP$rt% z+*FdmYI6GT)!K2QyU>W&vSAO@odFNJSMLeO(*pd2Dr9Y!7V9gzL2P$B!~&PrGh$_Y9{h&KemK?+kbK`A#`5{bt0kl_flQAa4~hF! zuR=0fZqj=^_smsMneR$4Txz8h8AESU)F-?q6BA*6;W>i*phT?FQ>d{y{OVMjAnj29 z@xXK-(Wh%3d)h)Bi$3Wd^t+XU34Qf+uGL4(--w}FvHEM>$O;iWwHadgHGb`TDtCvJ zfqBfAzZPJR0t4!_+O_Gr{pAWspO zmGePqan8s4}XX-M{%L#_?vXn1?P@!Z2&7D@<@?kj9Qo3 zWwUKtN3;&CgPUAm<}u#`L@)AlF?jU{Lom$zjuF#7XaA~{Bw^`@+=s)?tnUaGyOwO# zF^xx#FzRC6o0C#7pL~iE1Qf_A1hzgp@0y|q!)%oY4E#T{r)bFql$HNVo0cq}GMq}C z%D*^fY!yRuQYQ;-74&=L?kfy#RD^T;M(2v^f)cPt8~0wq@HHL;KApDrEYN&er@*>T zk5s>W2f;Y-Nq-lXjn>;Yo0ju9%l;7_mw#=mUw zZ3!;ZnW?1*!1?j6Uo|(^e8U|%2^0I zyysc#Gzr`*J@%uQeyzn1V4Pqql;qjnWks5m72Y@rO+iK#c6?Y39i=3 zWnho%w5mrCz_~mks9v@_k;(H(6!xRc_ym3vAA-|Dz6EBuVWOUyY0psZrE`Ed25 zBU)^bW^*z$M91GHUz&E>btz*Yl>1#O>hv(Czq`888*m;K2I-wsdpAs*N4BQZ3x?O0 zFaI>vyp#nmqm#xvHp@;tAkwY2qQv%v{?YsuaXQgk7W{gZP-;VNe_RInk(s(ZuP69R z)4)kC*Qm0?-7MR!D%&kv8sf%o6@EFa^e}AyCGE+X_u(3*f&eaI!o9g{MRh~Qy~|1T z7&r}X3+!Q0zO$$GI94R=xJTZ+q!qqXMR6=B0IgqdX`4hzAGHe>tivj|qQVD7OIDh9 zUf}MLB+b>C@V>$utHjX5q?7I!7`En@EVGKL@C`^2POK(n8`jqSF}4+4gXJ10L;@mr z9}>`nWpkvX&!e;%lgdSf@ibgt?b;u`zy21pBaq=L9-g1}FoHrjVv&atI=#DOc`}tE4JSV@{RLAjzW* zNY8;X4||(t&PsNxr;U&Pk@g>omo8LVh~7@tHXi#RK_^+GH`~v{HB(ztu(iTC!KY4k zd~6FU+plW&YS=BZo6UP70k*aVy&^jjHh*wNg5uEZ?*R!psVtfa`wE?7{9i+sp6y;a z(?!@OcDpG)`3%WC9W2@NAC87`+}_Tx)@FpLUnBKMLpkfBLJth!GFW3RzN*i++9BJg zX}cb|Kt`|zGL0+&>nb`HT#X1iA$*d;kTC7!{;kaoe0y&^}~V;8lR~&MT8_`C(mWm zn}0rspnEWTO#r`8Sf+ps3?x;D^x*l=)CFdDh|2&I3lQ4Jh*KQ~fWYui;b zx+;S&`|`+X&})A_M=*7A6;)HLhA~5iEzFK6-ci*0&^$2NRO{ZAZoREu>Xa(4mpAU< zUm$H*!+QFIWwvRlkkg_gXk-y(n02G;oj^q&a?aRDQM{ujq<&JBfa@|C&}j;buQkgs|=NrpHvt5Eo18ePXB-WKhD{a^>xNC#fQQRz*# zFS&!M`Xu9o4IEWlxe%fmHDQ>AF!h8gwgd(?^6hAyEUTnQqw zgBT=9zLmIkVa&8bezjZJTLkK}Mp6@vn!;}D?4ZW{NcrdmWFe|Wq)sM}BEGOxsKDu4 zzHY%Zt#l1!pX&O&>ZV{|moEba5!qV7>?ffeafWIm#*R4{-Hd05>RQ(yVi2Cj6F#CV zaV1#0XS~y+`dWsd8y^XC`gj8inn=viz%Slolgz`s8P@50V79aJA$%N6Lq3lAaEbhs zqcRo|;P2Z7CM{UhlY|%`pm_k60;*xcs|Pc@+%Z-W!loC=4|+g2bLbcMH$ciMC1L<= ze!^}+WL2koIYq=P#Oy_7fZbt&5{4dI4VhGw>@Bhf3tn(fl&t^g5_j?ahJgcGLgMcr zXLHM7@dKgKO1M-^R9vg5B;?w=C4Vr+#2vG|-fHgGbANxqDl3F-@MmBXio<^VlhXDG z7k+$~09v6nx1e&)DcW?{8S-XL)c#T+8=SG#=G#tmbeT#ZtJG+5 z^=U*apI|w|s>237! zfS{9q`Sz1iTFnXFarh$3bvUpQH@8ARU9vVEd$IoG=Em&-co?!*ia2+ik)9uW@rdhm zhHarYB76qRQI(lh5B1{~XA-`LG36fzpwTS(@i?pqSf~Qnn_9n}MOVpCK!MH>Y1wm( zs660;?vQ?lTTS5Ho^OL2kO$DaKFPTs!_E~G zPG~$N!;+C7%0}qkv0Vj{kc}M&rq&_MW1-4p$0c?9$nZcM zmfH)n6CNik57V|IrQOt0cg13y%CU;LDLm^PjY?U$_F3V)H*J0UMxY`-B`bDbItjw7 zrCj+8E!u_bm7-3E8+MD%bV5x%6YyUN;v8dk=|NoD;nsvi)KuGJB@9HYGsc0DJ{z|R zYe81-9A-y(5iWID&H}Yb$}k8IZV@MC1P5Z3;!WphK4nZ1 zs9UVk2|rJ%o7KP-oL^5n_Fxk;w*$i|Ie@3Ji1VOE(fSm;KWN;ryWQz=>#b%R9~xP0K|2qn@AQT*dfU5Vj0(&iQd$Xb?Y*X3KKr(4hWURQ_rBF* zyYVJ9A+?w|IL!%12p2"O@f6uqY^YP!$@jrN195a>KFG5+s~Gd_sfROGQT^AyDj z%O--t%FfJTk@YF~nQ$`pYx!uO`W2^loAh$RBm&!qx-8h6jG9=>gl$5y^2$7J)*G2A zv~qkLc+GIk@bGM?i83SaS#Cfe&TCg^)8Em9p2KftpY8?$(#0?{m>hS^d+VdFd-3=f zb%n~&qq`0dcw@QZ!EmtLkbePsxc@fV;IZ{WPXaU&>@`72Gl}9>r`qoO(b#VIhr{ng zAeT4Ol&m@QvrpkX&-4tOiMdg@*|q#QgIjsCmlk)f=oAREvQ)#_v~JXHMMmyVw-aUP&9v z5o;=OGyN^)c-8Vs8n_YzYY1hQh%I2P+Mj8C%ApeupPkL`*kwtbnXamps-+#8Wong~ z0HT31DBdKYK8O$Y!m7Cil^hw$a7I5IvS$?D=1+P?J^pZzedMAJn#?x_iN9v2YQPpd z>!xOFV8QuBhik8R5}ZK@$|>~r$Obc4P8qx)ScK)Zp(x4BZ<2z)H;Jq}rn3W9m1?-2 zoCQg?Hm*H&kv`e8xOY8nb@9G595Wslry#@2j_AMS<&gZ*Z=ycTarw?quk=&M&odSi z4@L@A!2dVS*wpK@{^g|jNipGN06 zO4FZea)x^DuS$4M1B=l(LVS-9xXKY^lLWqm+nnlW-X7)NVUztIyUeRR;Lp^21ulH3 zl+JY6eNUy3U&)G;Y{%xYNCrx8S;IY;;XZW;@r>NNKXAWq>P^Wa>zdd&PN9gzDXE~B z_^D3~ENvcqqahkA@-4PH9K{L5xji}^|3HhEQwV|3UF>%8KwftFF|j!Y<(b-fP_)2p z%zluGdYrL3_^9sM;`h_o_9%7RlnjkfisotLIBwH~4!c=MY0j4eTX%1DxY5p!S@8Ud z@V)9g$zRg~2wAT0)dd!cI1K8TuzJY=dpB?zB_GXT+CK(R7ZW#^kZfZGQw|_qW(f}r z^pe0!C1Ipu!`sx{sVaw_UzYXd3^a~{{Q`8l)+YM%hE&Z8WNzhJmsMUh^vzH4pK4~I zwk^(&r%1)98bV4Og$m^&**jtk5Gb4@3ihL#r7x0PA;R7w2GPn6!bl8tlRug-^4Ug6 zTJq{h>z;DbGu{;2wtP%UWxcxF7GlOOACmrYZjlHYV0;T<@d3Xlfq&_(#RfV2dRPl?L(da1yg$kkuu0DD;s~5f!qJQiTXU>!CPtdRbv5!< zf4c#=DYSRxx3a((Z{*L+Uf-@-O4_wY6QyM!X9d`SO>O#SV2{Tc!34;VXq%$>q?l-v zQcqGxnEG#ZF}*9@AK6H@((6V-4*Vu<<5(O&b-Qu>r!@q4%Rr?qa2g>0bt4eIS*9h+ zrJ`Eg6kKEUN+-pYvflBXbh`Y0WyGx~=~E5XA8~+>t8<+DQ3ASpFE(tO0|l~b&vw}U zCB`s+vAK_*0Qtm&8oal_Wz!Yg#Z5(mt&=0FSg=6=sk1xg(l!!onAMqAj zQ8u@|FR!Ksp)6QXc@7xk8{B(RDMm`USv6BRluZYm1}48z$!VBBzm?p{KBd6*7F*|H zl9{@F@uB9J+_^LqU3Wj&uem>>l|55NC^p5v?iHJgyBRb{d~DRWW22`P%gk=A?cJQv zK;MwURYmVkZZ#N`kGY^D(zp@(Uk=N@+*h#uTQDud#kK;YeNc7?Zs7Bi2<`dsiS>Fg z_HZHTssMUGg}hL}ttARY^*?{3;)b5Cj-I8M1z`hdB+*x|)l3U9P~t33bSi zEYm2?cV$6G2-2h`O^k=_t79V3i*XmP!SBE9v=p>Nuc@d(i2S5vF@lTV=zS4v!f z2h`vL)Vvrb3~*Wa7BQpXO^veOWic`@{&o%`VmJH#9x0~9JYIU~-8s46uFzD5QiorX zgZ?$o9?g+}vOl`-`Psc`2sZy?=%*ad*2~zbj23Rvi>+`kP(pP7w8#fn*D5J+4Va7| zMYB&1S_YAKD`mhsQ{iZAZ0fz_u0Qe%!J3i)AqU4z()z{sZFV%D{l3*H|MzMA+*&Qs zTD&LnG#um$L*45XA(J0RBd9Q!xwap#TDmZ-BYzY!05~^UThx!Ch&fFp--K#th}6zn zG^zO2(}zM^EEzF-b}0+tBlT)w!Rg>Da9RI(#P)bk03_h!kE~?0#pk zQ(!2yJ*^hse6m5wY1nsWpw?z>Ogn{lllB=0Wz*>Mwn#Z?_cq2GcXO-tTsfY!3zE;= z2N9#>;6ts~eAiZXs0ZaM4E(0!KwEH0E7Q(k6RG`dd+~FR`v%C(iJRTww3O0)RYQYc z;uQC~%uDQ4JssfoNtG36XrNY$)=hFe#NlOfXqN!LX7yOoah#T#D$nHYz7Kl3Gp(ba zjBvk-R;`!-MU17wDl$XroKwI!0$yuWmqbh%9Hkb^bqOf~h9_U`-@<+*q0~E0h7$i7 zJ~#kFyQ0A=Yz>I8rHS=rXZacyXu!i6%Vxk>DN3YEC5jEQn8GE&d(Qb%*ram{kb42|Fa(f%p#%_|s8QCrx zxI>-)tL*7185~tO|6W1(JrrZndg_WOy(Itx^+#nf9CJat?g@{7{A+BIlLH%wD>fQW`M z^YGHe8EGEdUJ{qiWSh|xM67srs3;okAY?XEXm5l(AGdCkIzHJbL28^S$0=lSabQtw ztHpGbS4}3(G2w@!-;#HHKSXtQ13^%xc{8cou;eh!pVloyQ=r-&udD>VG&Pmi21h2G za`x5O$_+SLgWl{U%Cvbb0-Aw>QPa40uUGeW#JO0#4YC+(KVkSAg9ixz|iVaV6YE-PZQynVEG+E z{jZ%4h1}Jg^t1UfnY;gy4goxH`FN&odV}MXjCQ(G%QB5|oP$g`Z*y9=Y5herta#sQ zPF<1bdn6|h2HZbX{2jd?fXg_YKuL+jbp-uF))bQSgZ6b<^&x6!i-)B9Wl+zxFTy9W|u2gYAE}9_)JG-bW>jA+lyTqb*%W?Xhy#WYfMj!yKJ! zKW4@R-CFi{RpV+}yt)i@ok%Y2t$2<$O`rV5tVx<@(+o{bvrXy=*1%`&Od3-TLf@MH zya4r*(1D1tm*ZEK|BC05B&PtYPSSyE+JB_Ims?(TR zW+@EwLnKX8cpMzpml;|Sv5;Fq`Ezpk*$Cendo-Di^5`B_wWi35XD$4APjNZ|HFY}&8#wVX5se5DZfmFO0Pfg?14QepbPfMH;7s+aAeTrhppT&AL;!|f?P zKwkCW6*1YXvqIMH&&_M#{kW1z<`;lc{xkLyrx9cI1pY_nnyPbG3u<{FTe z;xn}lnFd-8b4KBQ%pkDM7mZ0I&OeNeW)ax^db?~K01|r;9{eVDrOFQ8OghKD>Ix4m zDZiQBYkfsvf9mbOUjuO#(&E>JjrjnCME|iFW_soNpH4Y;<4-0f0vajJPUQq*S`z?9 zpsWX91oDE{&pS!B3*r{#2vS9x*U7}kjJ)C~@1Ssaeu+?WUrE=AyX(EXU!T1to0Uo; z8z`XurvIe8`hRKXj0nDln$oTSl}3+Dn)ERkT_sElM-sbKNeBkpyad7-i-MM@k>&dO z#Lb=%_EyDMvW&#{)nxtx6-YNK2_WFQrOQC*XnZ>aX-O!FITr-QMFt8vMDC~3RdDS7 zaUl$l|6-U{hIz9Z`677Hw2qTiwEzGBxB;K}X%OE41eEGH+=R1@6Y}J?#p-7^^%)dg zrFl>n?*6t5j?(@?`j~$yHU?=V!!_x4;Vc#Fzfap6!tOdnx@$v=9^)FPJRG|WP5Nf{ zsN!U{)&H3tGhL?)^%+Yzh37uX0R?fG=~5-S8&We~-`i|rgg8b1KB;8(+NuR^`(lY| zfsoYaQg^EpwXB;vZZQfJd2ld$=6UoknMfrOd4e<`Vi-HdnWWrfMoubpA^{>RF`8MS z=>Px(4FR9~ZbN?n2Wo-904|furajjTi}q3@*{NcKC7{z)|5}d}(55Fzb;4C?=~Cq)NeI;*4wrcq zWvVlLg@W_WbF|D_eW$lO@qc99+(#U#M17u>#jpq2kl$UXOB1V+0xT4aCPB(*BAvHr zE%GrfWyH%Afo^h}YaBqIo(_1GADjm65yG}b*WE;!9OuB3HA{Av{l^81AObaezbPUU z#Y2tJyzO2L(z=%V)3OHv@s_2K$Kdu@vy2D~(fl2Paq5leylW@P@V++|jz=5${9MSw zkL>3h>O+*cxz;N8F@EK_$pl&f_j?BObASHnUmSRTs@SgtefqMg#&P)$95ROd-#gv+ z?1+Wi_`whkI%<6-6U#T8pGQ!^pL2tEs(XdW^GE+N(D%m2{U+UO2}CUkqNOoo^Yyr( zsOq9TNTuY{&q;j9n4C9ufU(W{*i3)(Gm9Fm2aI5!PMj8?kcRLLv!G+Tc2Rk+=Zb3-RNFFHK>mg4;Xjo6mJ4e#qIduAepxLX2r{I83dH{Yu?JlZDAuu{&L!Tk&kb449;QLV2X% z-sll&4Sa`?DOdB+!3)-z$uyUK2hSmHVsPSvjzZ!|ygO0}#kAVtPq`}nZ(F~N7cu;6 zBjhRACu!i(uV~0L#^ArVP`rgc(~l2n_s+>~Xht%>rnJ`jMuEqR@yQA?Xaaw=3Lw__ z+{?AT+Bp%4cxoQ=j<~)K_U})a!MTs%o4V5IU#RN#aSquZiaFI@j%Dk8#aOq(V=q5cEz5#DwgdhC)*g$LeJoQ`p)5( zFFcw?jI`*c2W3zB2Cf8i2s(9MQdS=c@)|19`#l&tbaUi5gVSzi2VqiE7y?K z2w4CCCa6K1;57&>sWO-Z5&!3 zpBr-r&exOW2gE?ODK%p`)_p(5jAYJ7WZG)eIl;zZ5URP&e{kV`+9Z#f*V$hdpMK=S_0J+hw*6Zt z@7S5H>~qge{LXL3eCqd@ns$LSI zXIuu_xg08b%>V6cquNMhc*3`gM_2`a;m|G&QfgKfdyx$;lu`YD%!MRQJ2$|dmeNDa zY{E|I@6f;0mYO8eiXD8M;CNdVf@c6|#u?{WVGu zX}8b_K1D~I@Egr0KNI6`S#W7d)?6zA-V{Z-LK@w~U_j3|#GOjv0RgM#*XU-~E@$Ta@ z4{O8w_GK?mS3EUm+_VB8c&f;-WAB93xR*R1&;>PklMAs4C3~~Qib5YL17+CsFKzz8 z>6{2HIE1~_3fc`LC_#hhd+rblO?f|K@y?x2cxm&6j;@&Vl((&T@#Kzx)On~krh6Uz@uKf8@>T0NS&tx2{Cs z&qE3!=At4nMiqP-TvZ-tpFzTCzlL^8o6r6t+C>{25BXoOJvu`-H8{|5ZFYMe5k*G= z^Cwtsp`S&dr{F_aQX9WvczT~M6U8QXlj6K2QPHCN%Y5Yv>VBSvQP)g zzoZvvIdSHaXJ&J}vB+eCo{Pu|(S|++07mDudCdNuYicGj0GnXInt!bcT{g$}gOuQ3 zxNT$?7SN?6oj~+^yUsHaU3vu=E{?D+>!_&HF3M<;YPe<0=99fvg#(9DFjQ#b$*BVH zcFQga^CqgUNF(3ipi3h&c0Y3w-k(^`$+pwk6-yD07(`95I$qd<4Zage%D%yBjcN&Q z-Y-9B;FoW9gm3Bu5mm&Q3;a!r)nMQnHFKPki~=t25c6T(t8JHmuU6TA$%m#*b^J9N zPH`0mq$s3~FX`kFL;w9I6YmjDCaQ5@#YySqyr4I>X5LRir|EcoWFb-5EC!H~`cE%8 zo=w;VQRBBN+507YW&0er%Q2RC6d5%BZ33qNg-hp}&H}MC%i{6$JPvAJ6#2aLw6ewb zGzNY`>RYXrl7f9~=^nx|tV=si8!l;d5EMOI>xdOcX=RI|(9ImPQ9_HuqDqT6gys7M za9W_^2DK>32N3?8ksM|H;yLPZA>FTc(A_veH_Uex%ioRJ=KoUUuwD^v>^f01CEFXB zjTMf2Dz-rCP#Lj(CS|*aYXua&)+C?rOa+W<{tW{!ntiLQ5U9Rbr3|p+NfLif?{QVy z$FdLH?S&x!?egvL_p7A+L@m9q8}$yvYw7EC+_yK7L~Xrp#yu#ipMw z*WDxH#-}&_O{D@jjmkX(%_(EZ2S3Ix1Yr~3hQ8l5Dsp~82k~*{I?~z+p6tXcMaTBR z$Zz@N6@9sGhzi3AAAETXvZhufTWcSQCi#?I8Q~OL2eOp`(drAtL*g?yx4 z?+a^lk71xG!TecG!DeNa`J{9zxvKWsJ&kg}5G@OONYxslYBj;7Wfy|(QC@icjeXRJ znBTLL&}}F6{!ja{0Nv@oQM5R#wvCc%M(y2s*z1%RV)(dJbiP|?CF^5}tok=hJDs-G{Mbb<1zcl8^&0m4_;qp z#Xtmq*OrLoIBb33nsT*yaFxV<=LBRN1XyOUIsv5fQET&nm)Ck8K2Y5zbz1i+muby^ z+Hc<>K6V!hRP*+4+gb^>=9F9VA=mW)2I|hiQ}-;^d$$N8jU+Qkvd=A0R|uqd68Qc1 z3PO*2fe~c(v!FI_m;wg(z!HKu?btM5o5P`*Vw#7COc50|uXEQO2TwPLXpATZqm%4bDls;U%XGp_V>myo>aE z=jDt!&kX!5=RwD+)GMWDBn2Nrqv7+5mIooT77KUh?WR^KAQzR6WkV^bA2fV{Aa14Z zw~SmRNBo0rg&Co@hN$!1h~*(g3^RZo@3N!4xJ z8>iP%uqabd?=J<)w)ene!ikP_$`t8jb8Zp5h0&yO5}iLzKt}_PBiLA5jt|H^tbl1C z6CSbTyLSI;`eZS`{cr-2_$=E~x7;4`n0aDl?%k@$Jmeg1FOetBo$f-~aN<`!71~wC z7HrROmD+rGoq(TvpQ#Ss8t)8r7gMUBiszL6Yk!uM%9}N5 z3h-G5a%{Wp{0Ons{K3%L1D}Oqiw(b(c0{&f|B?BG_1#>p`J~4mj=sG($}FC1WxbR` z0(ia)I(7X7tF%0C=0q%ZAA3D-idU;f?2DEyypFsK;&>kEmv*MJ9IzCv*c1_b!tIAh zqT(#HM$ygn@P^Fn)!=cl4hv!Z%2l0lr0Z!RP>Cc`AnkUjp8G(^320 z)mUx=9yRJX4e4v?2hRYFi)_otLT~0wb=vBk1lIBke#E`xmZw2YfBoXm3d;8?XM@sh z1MK{&4^b(tm_Kp=^mu(okV%9Cl1;fWRHDn2bFns@+s;Uj3w>tkD+E}Re9i})w?trs zmY))_sO=;>Tv}NlV`YCPeNp5V7cu6#pOoz}_SW4tGbq9Eh0{bM^;?6hf;qRd^CQuCSa%dJ3Xrb0?XqlU^)KomCcyTNjQ+MinJJL@+ja6BhV)91>L=D1&| zh;>tjA~@oLv(2yY4^%n2P{a}gnXDV`<1^jl8d2?I1HGPx^U*rp zy5uUtbfj;^cJWFreUxYX*qz!H;1gW zXok89{Snq{(@GM|=`k@r8cd9w!KL4~?PiE0%HdY1quo)7VW?=9%xYUM2zer9xwlk4!x_`!5Owg0IfBl7A zm9Y(uQ3B_WQvJPFEOW2bD?NYbcd)uy)Wn&>c9T~{sz7X>86jWqQbZ*MO%cF4TbaIU zrdzm8^SkGUKBAxrJquBIdor%R6`jplpy97-MhGLgXKNx2W5^`W>@gEg1lo;VZ|Pqh zU!sVyzl`_Y{zWQNwBB?=Lwl=k-W9G+dMMkZ;xm>gX)&UL&6_yPy)S6~L!DtEa<`wK-3|He3F;5#913R!n%-I@R&h<{S=x#BF_rYm9;+J%tck)G}JryVO3l z@YuV_PnK=*JD+=suBohH}6DeiliOl}}_!^@B60$TgCc*;_78Mt8hOiOs(9Yz|%Nlnl!z;K} z%whyr^*oed(SvQpRJ;y;_8ffGZ7gL{Tu_Jw}1YI+E~ZfDO*3zW0rflg56mJqPo~2 zqEm^hnYI0kItk_FD6&?_E1Y0Ho&E!iWzvAL*>O#w7IeDb0&FGfOO5u;CDQZpNQqF3 z3MZNPXq@J#uaiy%;(SFirt(RRMVAQCQ4f4NRwZ=-71q;nGu}4p%n)|z$s7a9VNe?7 zyR3Uu>OZb}Gw@47@#JLvd^j!9)V!%^_oJ=c)aFBQVPhYXDck7-mZ zA}q59ha@)T{W29U?S9I{v;6)zr8KQHlr;uCGuzX0Kawv8yLHlVBTQF<52}icY4A`i zu>^D@9_r07XQp_4TmDS4W$vWdJDqa3`zxA2uNp@F>;$n8hP9^Eu2%*f#O9eRu~yw4;ZJW`W09IPt$< z_CEW%WUAe_OxIbJ-?qp7NFET8H-U~`ZuN$5DMGze`G24Q_lEP@laaj`KfcVL6{4ye z%)L8r0GU6Y7$0tkuO|jubzCeX^ucYxJ6CBMASRVh4@L~<^7U()w3y>!q4kz%raNEZ z-nmb>(HTg;H*;VtnRFWq;!o6WI6C#|l`KMISv7%`3&r}m_Mtf;%`;&#(9ZbGK zV1qoRJI3_QK#O~fc+osA=D6v3n`~EHVGzW-2FG*01fDix`R(1=_>Wmm zr~c@j4*N_+_xWw80|dvEPt|Z6AKaI^q}LiGGh8>6h9;*(O_6JTvjvJn^t<(eig9ag z0MPh5f4z!+-3>*btR&F1Tyu*y-u3rg4ZP<`&dR_e1;~G)eES6i3QUM;fFkKEdfZ*+ zue6L-8ZqR={d^dk-QWWBS`!S?-+Kh>YqwozSO#@hF~W# zmJvg=I!C#KbB6^^yt7z(`qSuZE7Rnb-2r-6{xHwsEU61LH2?m7*$)0AZ5kp^~zmgT?T|7=Ks`F_L2~Et@>Ja*sFt# z8}`7vM8-cQ_SVZSsl1$;j{E2!oKZrxuGs zKbg#EN*>=&5(|Jd|A=P*G-(_Z;u;9Ve#Q!!7Q0iUEm)w4CLiX+A#=QJUIO95bI$LMCuGjE-6tE+_I+wd6#uoz&NB@sgMaE6ZavhT(wQaO zDx)8!pyFung=q3*=jO2*6=%i$t12}<8S>da?SB-E!vuD>34D;UQ1q%=`&IMv$PGMy zum|72-Ef;JRalke<|qJJO*v1NsM&~t=JS!p0@teF&hd@~0~dxE6%eyyc@7fJRA0C2 z+|d^!5JT~eG#raz9aojX^9zGfmUf+d6S2)wpJpB)&mS%g%bsO@E9vHs94IL${g1oL z_bC4gn$Y_frE+5ZXg;#&^Atw<86$Gb!1KAe5n^n{&4&jI1j|gO78$0rF8E) zmrsX*FhQ}|c--^Ik_gyvE)MHz!=#3~2y&e%e4cNn1?8B+{7+red5#`#IZ;XFo%%B= zAtOBo9sBu^&q7?>e*L?(CLwyiR4&*urU;m)iTQ>c*hT3di>H60>%;84QG?BjA|@Kn ze>g;x`?g1&^*K5d6$Rw=ph?yq?WB?kubc%#x?Q5R2f^ev`fpuLgZwS=^4Teq!GmNJBMIVRV)#p)pm`Q3^CXOE;Yz z4~r47r1_^6h;-yRaeuv{WDa&I+?-2-&UrkJUkFNU-Ym^FRt~YGpR`J zo+4bIO#yv%ETwxO2N<1|a5D+!+tZ|uD^o&v9&P?ci|OIRhMTx$?Xb@x3qej7QUcu= zI37VJ`O!Ia)|R$4_DLJFvY%dL0SMGfobg}DFRC13|L(OHr}>i0beP@yLwjwHr}V*h zv)ltH7DG9kSKbfT$A6 z)%+kW`^O!prUhmoLv98~P%~!FXHA9}*eA3PldkU!g zhc$vbgbTIG^Z7gD+;__>A95Ncdh-a>y zg9e}W+NOQ<4U@|lWp_`^{iq2c?z#LO%C4N5Y$cLR*JLMLjYf7S&uZ>y)3W0vuYeZX zDeP_pa|M}5lWV5m1&lm^=wpU-@c6x+uJn%%5)?fc)9Z73T-B=&L#0 zQ%4yde-$4Om=%Ko$n_o$Q zHarP+YdHPo<|aNq`oZw5I*|7;imgbX3L6&;>GKcpp>kan1{NbwgIR(hFZYoBKVXS) z{2XcC+LF_aJ{%wG_HT9V9t+_bH`hSc|FuaJzRI)GUM)Bt6-XEP-iPig-`XAuP#GP) z1D3Gz%M(*xuca6{D;gR*($~t>wy?vLKu@ln3;Cg(gdfE#e*aSs2AQeD@J&%WeC(V5 z$}@4WQ3D8%a0KhxhJ$aTM8WzhBML7O;rmrsEkbX_2ABPcXRH3wBkeLnOseV z+!+Q7C4*uJQyyO0Iku6`Fxrn{t|siSgK7+=+(Vp48>z5os9sYvf_K2iXi`pNs*jUy zHmX_2(8IXGoU-jp0f(?6xUVduSk?02Zoj^F?yS%4QEmSoL!YFDadC=y<+pCGQu7(< z`py1)3~@4Ujr=x^LJ6GAvbP@^(aI<+?bi4IvFG$s`F#^t(bj9S=GGmXoacB`SLgcn_GC zvvOgbZg&D9v#WCuRNtQ+BveF_P@F1c-FO3XIae1Pxgy>gTVB#CMAq)L1a!D;*Rjcv`3`#<8;uW>sTUInZ>aQx6tMUBPjcwxf62JVL z26zv%!k~AfT?Zw%SlM{Y8V39=HYh{ph*RT(CD?}I< z{LQKO?KOt;%aQO3&4C`{hDojyjb7z5Zicd1f3fQp3@0}KFkgfAfSl2Mp$6lXVs*wyc7nIQ}XgmM6u7r7-RljF9k`bg6gF@3{G;|;XAsoyHx z^sp^S?ZoY&su?d=k`*mv4j?UhkZco)3}yhQ(`M=J&l1ntC}FX-4w*WvRpY!Tc31{t z^3H{1Psodfo+W(&N$1o;$eBMLrkCt(HTBx)6f`sjYx>IVhHzrAIc4_mROY-u76Dtz zTu5}qS{M~;nGhjT&)5w5)iHhn9-8n9Rn6Q)F0~705=yNjbBwB+mrVP&f4vq0`tG z21#;kNeD1+(E8hfedSwOIo=Pb$6l;65DFMMo)kl{iJmqql96m)ry$l0t^&s>-O_G| zM*kT6BrIoly!8p_Z`Hk}%S~H7Rq4`)=0>A!*m@jvwsXJf(_hS|gt)|At`j zauSWnilnb1cv>bmoVV_SeZT4_xX0guI8`b5?5wy&YoTfp?RLk7Z~Mo)ATTwQZP*}0 z!``E_Qe9^bjbTVy0DZZH!cBhDYsu}vt==qP%ji&I#$ggKS8C1aB4;&}085?1-EjzE z_rdaqo(%rT(*20QY#%Hac?rA3Qb|@A65%JDZ}7Xz0M2hwb!N*2?waz=#|OKS@!6d+ z$2A3oJVw&qVYGH%lhDPlP1s=AuDRbNeL^k_tjV7!H#Q?HoLOQ;BfqGdbB{>BA{ z=%mJyPmy@EGtNZ-JU5d)h90!p;a?k`K;W4h*HLbYBU@bIeW6YDK=ax>zLNGCQ6~{m zngo;Tl5|v6r|q>KlK}OR2_?oYLd$y>H$dDl*~||Lg)0>sMdcCD!79`AA*rsBW=}p6 zsCg2eoy~-9>g32Uzxl^s8#T&61-Do+?-UaBs&JdBF$l(`$19wJhsQt|#tZ9Or5IW) z#y8V)tvtwaTZJ5evb2hwO@S8S&p{eh8q|I`gn%8SH{(NvW4o2W<9k>FEqJix>vIW2 zklmfy1emS!-o@uGLcZ^@2FcOwdWG--AdIwc=FSr|Y@BX&fgk3+LhSExVvHwTGU8&7 zfYSylMMiyu>FotEEdVRvCF>(Yi19IIIi5CGkCVKKi#FHpw2+lF+w9^Ch=3GKGOSbe zLj&xW_F4D>NvLm4yi|SO#e?vs+Dr0rlH-ux$~7VGC4N>l2F==nT}vQ|aYGNZ_Fro7 z@>0j?cgR~Aozwf=UIcw*gs*?);Jr^nIaEw3H;5M?t5ux)KI~3}Dcw_N8n4Bv!P1ZE zrtzI=c-}#q#mHAA-wQMn{8EN|W`=rpzPRD2mAel3cAXY<95pH>y{Liu|FWU&wp1J0 z#-mPR6NI_dKhd*CN)!(93>}Vh;wp8(bHc2=fiZ8N4On(L!<@k`XM01<-i?s;Dl8vZ zk66^7oD@V-g#i5&6?8G5w^taf zU$>Tk_lQk|c+Z(Z(0|{=;e=8aCL3Z(QRk1-BN0$3g%j^c!rjp~ zxE9Du@9WX!p|follEuG6xo-W#6-600Oi6}Cp9=acjFtOoML$@^`~4MC7OIFeIDG^{ zPg_L8LzK;G_qN!>-I0%!D-358;_m~B` z7Vv3)T9IIsz^4>?q02znEoya|o;w3s&Gn1+2cA-%R(J8@+k|w9*-FN%6AK^6@0gKZ zkTsA&lx|3;G*4|I1+-Q6<1`I46g5N#9%gZ1?#$Q)oxO0}n!9 zKxSvTHL*rc*>Bu1D~t5vawR3D)b(#&4ae?)d?UzMRiZ+Rb^BMIEHCU+STFK$VRZ-> z%2uDhn!IfU%GvDl6%66bx4sa2pS90fbWW(|0n3obG7o+z7^?e(%s8&PY!0yGFln({ zCLGgiM7t+osY^kT5L}n*d2=hk*b91z$m)9%Ph6Ts!{&2f>ElRd0BP#0c^P(Z*)f zx_l`r9hb)~^J0wBdGba<#W8Uq7k)sUAmlcFpq#0?LH_>8{Y5QKSD%kR8Z3a6rDC;l z>PH(nk1DE*VkCfX4)8ovd=WN~ELUxog(&DR)$p$nZAr!zggPNOT|7wk6KtwhcYF*{!ow_XP2(-eTgf`Q}bbo zE?CVR{^CEk6&rw}_o2atU7c%pKw3LgdEh*W^Au+XwIRH5YdX~O8ACII2w?g}$aw+H zF|~_9r2!~~7(5vJXNSYk47P_(V4FsYLex(~pZ2Ab4*zb_+t>P6VIS1MkH|0O#YanX z<$?ly7mPM7_{CVqSqSW6hX)&ZWSv4J{NFi475av@@F+d4V;pKca{u{(LFIc;8fZw# zm0QX8?lHGKtqB*Uo`Rq>gSf0|*BmLzB)?StM+U~pon;)fQE~vA8l!Fq7|)la)w<|A znn}4?`VG{VZ~75+JsZX}!tfx)rTbZLfdjMRasN9R^AgK9o4DDPd1^VOs2b8i7Sz;B zeaJ*})+0f5hDmD#A?sb+s2Hd1>NlN+??f_#(zXO-K}Yql7v_ds+%oXB1SJ{TODS(p z^lw>JwIDrofV=vWoeXn#5G`H;Y3)ojskT65L44T?HFtUuso#t&SY3oXLFl)27URE| zl-ZzE2F@UJ41MZQ4d4R9ahkk)`ZxnnY6RlZ=nXB$uX(=WyM~X7pj{WXfga0=nXjt7SytksN;}Z)AgZ+% z476e2Rc$7NUWm@&uGo&C)sjh;13JdM(|lTboW_-B62ai_aW~q;8=Wt?YL~U@qCBJC zE{n}*=~#5)j}G*QNX;yBu_YcooEsC+X{Rw$6peMHqFWs~J`r|e3wLkZPPPxz?lFDK z0#!;zSF;xi&x6JpuU!}6`u`>hqawTFyccq!BEn7(5AXbSG)wP89Hm^(OhVcR<>Jlp zCpP{$v8L(b)ek6uO~u;1h_IM*=>S`qye0K-*hjbsyzJM_;_M7977afn{4)LyFuO#c z6X(_n<9tD5&ny1rU3fb@pJ$0ovmo_WD7+_0OV@DCjAebJ7)a_Tb|*>etyHfYy)=PR z;t~Jr;WZostH{Gh$X1lTvtwH%eK0YLRBzZ*!+MrK;nd2Fo{{^ye|pEQ%PB(0%U!}tk+sqS=nSK>2SO->_jz{CDz`leh4$XroXNs8 ziq6bFBM_v8Yb{2DDD=RpZfD;Vi}m;-X;Z4=c=;i>)dJYw8RAGW3N88`ot-A2N(O^^ zOz>0rg0blTi-blT%d7^CR_SeLFdu7HHIqAq1Yf0if|tS=>mU`mn9f&(27WPJuEV$C zsI!?i4aI)qC4_Szxi2)al8yL|r`&i`!Ew&VBj-^BiQ(UOQ2a!8#g*Y_jJBvXi7`)3 z)$D2rCS={AN&mTVQ*rWaL;E$?~2E`(Pu1ljzjG2_I2U*nXqX#fBN zm;s(WX%OE44%Pi*TcTfCg`a>EwXfr0vCqF@UnkWSXjj?j|6wB20t1+apvLnz!6?wr zvHb>QQR`Ejd!cv8t-c|)h~1I)9(!kFv-|d~!ej%jd|1#q_(oAf7~+Qgv6M>A`1HP) z1tl&36L^|%ZxVLVRuFK%3dETeTI9qR>A)<6dplCx%5Yp-Q^58g|E@KZFZVeGNQoDe*DAb49zFt0s+KSYoSXz|#mR!q*g z*=vi3VZ-G$7?I~+g}p;8LPw%n%$;cz(gM#Rv^JNgCL}h$qV)Pwj_N~&q7l#z29t?d z{DV2&AYjjO=9JY*jLOi!YICwmd%}~bAvl~d{*EM^gT~0X?435S#9-ZDT;p#}go`BE(eIy}l(BU{0{O84 z9x=O^M6|BNLu>xV4Z+sd;K4Il{e2`taGqgdKW8If6h^YWF`E{GZvQuGLK8wUmyMa= ze}-S}v$NlCRtM}M*2w`N-&U~LN{LTyXvkm6S-k069Y;~cItX83`U>;nvA6(vWnLa? z^g>a7DqkOvhdyH^W3Z6`1jkDh(uz7|)KG>!)P)x0sSIY*zyCO{+tD$&-wAxY<%c zSMhw;k?K6uP|AH=V1`e`Oc77aap-)1ke3-kNhhv|IMcb4(z z))Oyjl&)Ro(PE{vUd6DAcRod;2k%PyZyB_u+8YOaRgS%bztDkfz2$XU-i#iAvGcf_ zcF@P+r4gjMJqnQ8Go-WUJ70mv^(mdJq%eLyF`4*Ze@sFgZ(_)9UAcVYk}L3S zH#iTugrm1pFwx1rcTSv&i2h;Ll-z*t?_|HAiebR{b(|Q66mrplOc)W)#shk8Y#a^ zjjlemd_OJ|M4*EOe9+X)R6@(jDxk1)PgeOrs47Okngh6KoCz#{53mmZ)Mt3aq`gTn zPmVE`M}5^ULy!CK?G%H;9F8dGGy%|DQa}F-gxCs%lL+7kWl-#vR#?R3)j3@D`C&43 zw#+kRYi82!UMSW?ZDSC&f?=d}_vfp{?#4%p^X>QoBj*9w zA4CmH!~~E#y}z#Zd25Wtovp?8DG$apw?!}aJ(S;vY{4HLFKhu46|Ls|%zY-YU;gt< zPI1hOYv2I7_8=@_@~M0*pK20ON}_Dg?XDY4hg*TI{tAFfzr zXi~gvzCUoC@J$42zZGyvZ~r-Iw%4%lN26_R(k7AeJ{n*$?->}8%FcWS^yts068=jPGX5R3p&PlYflZ1i zC^<-Q&T?dFAC;Gr7!;d#<1pmF+0fIf8~2EIk;XLaf!47CkB~iGm($eI(`AA3tq09E%8Mw?4FmQj5zwACO*~$jc zzcKAj0G~5=KB81^6DS_VNh?&!UGf3kDSN55*FQItX@TJxDkeNUahe$TFQCn612Ib5 zqeW>J9Iq}|zF7T`YtsKd5HW3MP2g{SLgVd5ub5B6#hulEW6#-zlFFSk(!?R30|7K$ zsH+$!4So~j%S-X+idETfB(^|mzMp*W{}0|TprLZQ;)y#mlDI7f@dO#8Jn^t1eH<`# z>iC;MVMAIC(L8fKeI=PAG5Z3Il(?3ie997)Zq#7latC3H2@oYC%eHx;jUoWr)%aZD zd%>G-g4-azkZ<>^@79;lM;FLO@KHOr#eWgmMq1lseHNWvU0kH0~87c&O1$P17H5T{jO3ogLp#TM>c>bN#vqstxOlLdLNOV7dWX z5!NlH@+1D$Esjh9-1?6Xe`}W>)!+dd1*|M9jk3u~!ouSy8>=!}H5wA%LEgA&&(b`I zRFwuh*<3#UgKY``*+ZP!Z+7?{dIpnd(D&Cn=BP03cGkjrd`FSavoKCpGoB*)h^P0A z8pLa*i^fMgl-vHY|HzE7W{aV$aDUuKhu2c3eJ|;Nl4XbAk#kl?D{N{fyY$w9Jg^9C zXX%&#Yk>Wqav;A_b?*@f!OTvD*btt-Ch?unbqm{SooDaH@h%D2dFi4kq|vBOx?OJA zv4#k2J{G8UEdDi?x0iLRm8Vc#K`P#gVuyhM0451Rnj|2Q2d`e~_%bYkE5Du8>g-kM^tm)9J=)-P(*E90xa%Uhb^7->_ zc5(L*5?Y?4zTtIMsvzN5(hyCjFF}e?r;W~`>Wo(4^ff8P3-a=fPE;h|O76D#dm8L1 zOzRN%Hre1_NlSqV>q!#xf4(}nK@an~%}%v;Ls_JgNn>8McvYihj26+zak(%9-vP;;%=GKZpw?tHL2J0 zF_5o0l9AgpN&B2K57Yb`7ZAYkP)#gw^?V+z1xtw3rana7lRJo#<7ofw zoSQjE{scFyYsMO8M!sN|u>xFjx;M8yUF{X~s z5wSl>&~f`pGnsPM3r|7e9maS46Zo(z5JOImy#yhbJdds@gA(rv+9%VHgL$92EnmN& zdif^2tQA@_SKv$BxgnfnKAQ60Klv4Luwz^S>NWwRsR)j@!9Xz)_eUw5A_GcF3}2aSWO>^TMIZw{imvY z5L^Y`;FW%#1z0K-U5n*kS>D_tI7NkdO}XI`LFK3e&9kf(n_1t!%H}F~A(fRf02f z?ITj!eQ4}oYGE+lIN_`cVSW2PZgK@({bEsmM$^wqw%vx-0LO2Ui)g?!`8XCC= zMkSI_<$>F)uiNAR9Vl)QsCkIPUcBGbug zXOkAUa!)LHB0a;`>F`KQdF<4AspK*ova@SkZt5u|o#%4sD6!|c!o9nRi=MBx-TSJ} zViK7`7>+GJgNtTg)1FpdJ|0gM?GeE9X&NM^m%QM9;^Es?We$lD7op93feb6HFIzXV z75Fi1ivzWizlM*uv%aiCN#`Ca+|srSId~a3XRwWEcjlqZcUOfObQRYIj1LFO!y-F_ zFt5bT^B|L^$_E#io@lM=c!?iCXNKj1eP&W+FJ5Usr$|<>2M8w$$WeLi&ZV}Y9ZyVV zPco)HnMxYlgt;pi!A)NiLqM50csM+D2_2djd^A73hv|VI5T!_Oit!_~b~Z!y?6-8w z!$%XgWYU~?$r=8lMLhf;h&cN+oyjYVlGUH&Ix*ReC%By8wwMwn*1Lht%VYU!V`ewT&x zKSF!Yg}tcC^c8T*m(5m7F*}|*fZwsZT2nsH&_ZOI?IAI$l^o+g>`iOZPq9`em=sYF z%PrAtpd@gch$@}{Nvde@1M`T_QpXi4(I9vih=(3bCA;?l_kw<#6A)?o!!-E~)z#ET zO=}^b2Z%t0=@`T{DOs*_a8&l46cAkps_me2>rSKcbj-2Zd;RS7wx$?N7Lg}zzoHUN zAHZ6|>6%Tv?gRZS=5kQRgy@#tr$KJiNLj`+-aqIHSUdrr@=4U8& z8;Na5p~?*62YNIDU#zswHG{ZO;Alz&Ma17wCYr^nMdxmWnTp*t@EwtSkQ!f`odc3E zkK6GeaQ6HZDh!ivq9n51uXT$~6zK^J(PR!*4jf@EtnP%E%`)_zy z&y9|ECGlw}cliIyZ_Mc8AzZW%M|v7j=--3$C;O?jU)vdMOZ(o$8LQ&&ogb(e%H}|A zI38_mE^he2j>+#+Y^gjjidUFCia|YDCb`k&l@A^_Ah4n+G^qwFo6-bB{@v@g?O-u$ zr<4%QS7T-WM06ny!TA0dzo?p+W4VNPk0W1w+^Kd_L zyP)77q3r5hGfpuDx!DufY!LnJa#GRg;0(MIL3znbaPLpme?NwV*=KJ4tk1@b#JUj$ z0TrgXI-%Z#L)1ifx;@R^Egp=7#jd}QScC-|5jXN1U(n`+V}zn}+uU41doZyw6{xrT zDITadm=L2p1>@Kts!$+rJx#(IR8l0PNdR@qDcF~_#MYwqd8fA(I z6x@LW6I~dta5Jo2QopkO{}Rb{eySj80&gd!L?WEDj+%>Cs4y|UOBQn5s1swKc;<_) zvS3W5XdE~<3>Ro?JE?T{wy?j1^=Qv_<`U7E{N8wJZ5ommid|xJHKIdF-=pR<6h_%7 ztD$*wK|yk@UPbM~2)kJQhw477$37T^Rk=N7zkFo;s3YR6*%#f@ZPIyKpXM85jl6Mz zoBnOCSQCxq;ElY~Kl9r!g2u0+*qkfhKusFK))JxA-r@TQWW?Q+Z&R7xa%yx*qKC~DBP6;qoOGn_X+_T3wiC}ei!+~rmBpycN3 zWD}P%2K@ywsw`1hbH(}Q{`G*NpGkyJ=ZDAh<=2#n_tRV|HL<_|)BLahE~GFKK7m)= zX8|I>nt_a`rvFhV$P*LJ2ThgT`$*d2zs@xYGyUH}br?h(Ma>c6Q7t0?*}X6fureH+ z3R@&aCBC)sJg4Y^`B3P#uoXeu&b>90nu6m#(q&--E_a1Mv&vKUo}!1G^e+s*5Z4WB z_2#u;DswoI0*ge|rVuuak4!x9nY*0$juAxCIYXW=mit&P>!hAMX`9UX$WK|NO)kWBC5o06__x%u^N^5^~<-VRryoAN(LS)zQn4aHn|bDfU%) z>Wj>>5Aj9nn$zW)&Fz!}S+jq}0`_6F>AH|@LoR(=XGbYIN)1Bi7aDGy6nD*yb+sIn z_oyC)5W<`$P5MvP6;4`NM;k}&U;RO$+?h46ntaKWN7gS>Y*rErPl0>DM!Z9EWk&nUe~pY*{ey`8l{>d68zUFc1tqpO5Z= z(^U9+4t>J0qJlPjizdD+yiYDQnne!A8@W??NV>Aof4hhPqmd12Ltk>)9QTKGYWZDv z!+d6Z>l90@q2B3Col&gYB*g`ZTu^MKOzMjWo)gvKh0|GB%ccLQ%NT>j$8OtWNzi9p zVafbje;%#i0^3|C60#L}5X$SV3A2VzwrZjwpx8ROQJX*v=it!_WkC59mS}H4Zl=U6 zs8OHZ4W^z;6Y;=nW|}ph^}4f~)>6VWk4$WAlZCsp*bQx86%1~dDx7~qyfKkO0S4+% z&e@*OYOy9HCG>G3JHBje=Rj2E&o9P4oHJG?K{8F#=y#DWMwT&|P|4-_ol&0x6fz>S zOf~e@uz3s-Vvw{-K|x5DO)9wg65MrF`Mp-3oDahn7e*kNZ_chp#X0Y>vP&@Qa9*ty z_5Ok!j?G~Ua642J9-9t!m>Dq=XIDAYb){F2ak@y<@;UP!9jjJ-MT-ia%0q3$+QX`b zX;H9>XA)j?0$pIM_Lu@WJC+YZ81uOkZ_hWzvNSc>th>1G6iagNK#5Xqsj$n%PmtoaOl2q1q#w z{&Z6clqAsS(>1PT0R=#$yVywmAu3XDwJG0S1d%FNj2`VvVzBqZ=D zPKD#+T(o|Sb+|H8h@GGoPsMq2Vq)sElNmG7L z*6uK(VBJsxIBY=x0!z?`md4F1j%6RiCKYS1IV|?+BPPc;P{bxZ3@4mCutZe*bv?2d zk?yKLK5J6Gtg%d^ww$0;P}R+EWRZKU3u}?dB>+F&%jE#tKsrcJl3#*HC&}+!8306% zj{*K?tW$!;icH~p;G~rh2Za@iX`I_4s)&q|y^1yn65BC}yF7=v2C)3cMm2^Nx7}RX zN!(M@CA!bE4WgT9zxDi;v^gjRZV@joV`aE*14oMXP|Ch){Y}Q9DnGu?nH098iIft* zMe;+aQ@DTA8C1mwZL!4kU;+=7zG_cuUhFl$r{coG-5>yv|2LgyK4TiS04i9r&IrD> znVFyA*Y%kGisk_H*1ZY0(^(5sL6b0w$4;d=xe{f#xPlK0^s`Tj$^31&CHkc>|zcp%U_aI z(Cl{zeMqlT1NIjt#-q8yoEE)2?Y&s#?ah4(lCX=bS-;L4cWos*vUi1E;h6YaKh$&? zZ1i@~O`kK0vbZAj_7E%oM;^MJcFMAqTE5V+h(bTMz08n?la}w$Aqk}}jiSov`jPA4 z>|t;8^nEZbaX+RUU}$RtVcmbQnY)ZWCHuDjOnm?A_98KfC=OVSE&b^7h4=kMm!FN5 z4>r6|(V&K$QajY1?YE|HazL)s=$9p?`m}=J-35@CFE89^O#}*!U3ZT127XjI3P14@A}9^Y!HeA{S{B;RBMt-htk-5hIfn~}BrVj3yK8L9NGHs{TBs6ZLX zs@TyYGnR?Lg8RBDVU!W$^8j)Ut}RmC7@m6me}jvc+kU#&It%(VIwH@9IrbYZLeS_6 z7aQPm^rH39l-BWHBll_HoOSRN?>dojW;dOOZtzA|)4pBnoeEs9LK%*_;2_AZ8NA$S zrsdJP@ynM938|@g$6!-6Je=m^*w4E;ZOhFfgidn6t;K@#N^CzBGb<5u{hMZNQ(kZ{ z9K@z2=ng1A25|C#peJV96FJV^HwQ%CRbp_ujE->k>TO}1B}THK-LQc1z(a>1eo||b z29a%NGLd^-%C}~k2)5JI4Xc1!KrK`f{n$AVfz?w|3*m*<7a4-UR@ytwE%aQ}qkck) zp;+VrjuVtaMgx?&;;;g8)5Waoo9-rJA@EZ)>cIVn%cb8H-6Me>_HniRAl^Kr^A~m= zl3X^UNQZvYw4@FYEqDTIXy_ zgA38^P@EPEW}EzmZZ6CAZkJ2ShE{efaHzKX!E$;1U5uSd-GyQl(ee`bPU}++?3bm~xX8%DRJ9PTdkM?wS+2XbBIg0EMs3Oc9^3 z&pa@{!0-HYE4IHY8;My#2umXk&ljK7A`MSSjjD69QMZ7D{g+ky&?CKH$0j_GrR^gQ zw4t+n#aY`x-0p$$3B97x?@Yf8peETGMN17^r9?Q?#jYkmHeHfavvn49-V281r31gW z_{5lk6txs45H=gyT*q*K-ZN2k3SUO)xyQDQQ8{=2*r?)O5n`T#qLKV&E3y|Y(6+$* z$Ef%q6u-d`_AQC8eQ9D)xNaJDZt?n&TJXPWu)3XLsKT0F-A1CnEI;7f0pWpYCL~DG zA~sF5o`I=U&(mP)89k<|y5sxy^R9I_t8x!ERiySxk4PcIXon+(m*R=?Lr0w_a8Xh2 z{R7dy>Dx5Y)XYV>$r~ziVF9bQK}*s@zx|$*N+w-_)UNc0$&ozhxFL%1mD6X1W;Fig z=FH2gUYv4oiu&*6)TN<@=xIjCSj5hWL;ZywH%|CF6v&WWG0m5!@wHo{yZefBhAcTz zWL|lr@#X4eNsPP$l)cJLD~Gu`jS}Jk<)pD^HRGsMw9ft^tHY%P0-a3+-(*NC-IC^w zFiHGy4?aX0Sj?zMTHy2rU>XKD6C3lo5YNNl26Tz=U)TJD@!8q8)tI?#&4wb~1~F6< z4Vow@&;SZ*;gDpLbsUJxDN83~<$JW#{J^Is(^isx6ID@l-11+zHX5Xd3pheQ@s_N; zYbGSiBdI|#R!QVmu1}Y?`7Z{`K13$FdY40<++-fQ+x$blvwOa@pZ0)IuDoO)ok?Z_ z(;RhRI(Y^Is*!6$y49T;*|nIOltAWa*mB9e7_tu-&H_Q!;0Mm-)(hhY0ks=aV_Rb0 z>{@&kLv7~2ZeXfIqsmsI4h+sE)W=*Tam?X90oUsM;2MDI>qC#W0m>>cJ@HP9gO0?6 zAM=z?iHHNU-)$&?xB&BC5rQ1;r*TZ?_IU4`iEDv71IK5@?I6v!cXzkLe00(ectURm ze6g7|p;6~yAKSn7v&uYld)}VqnvPw_(#aV4EdpYwRgOS*Lfeuqf5$#)RE+_!7n-+) z;N4QGR*Tyq*F>~zK6!l%8{EDQ=-AXNx+maVo4+&Pn?EAi8R+eQy~~~6OSTLfxf9~( znd1A9=L5`|KDpf$00~eXe{58Z+1g2hc!fG6=a*OoD%co_@brS)7Tc_9%T1xdKZ+9^ zF|QUIAGtMi(sEk5y2`p)QsS_R;UQB<&vl-zH2LK!AiQZ0jAe?f1{AQsNW#PJgE_vO zAc9tOyJ(mXRpn}*a>ZDnI@NuiHzVkdX93tz+FCPGUnuj2&kmZ7c^uY=QNS{cE4M`SZ;W?z1m^;8) z6bO{UIczQbqZC6YgSy2*JH3|zaLq&_&RN?IRQ4a5*ok^AXyyzDL_}Fr``7HqV|$44 zW0HnB$F~#gv>6g_yP!FBC4{;q+|uasgK2bjM(Nr<<}xO0w4&kBEJWLl4VhR$2e+aF zQy83=;fKFxP!*%tS^8JvD;F(f-`+0Qn{`sM4~2K_xX&Wv?lSFTkIV!K>IHtx zI1=1^CDB{Qc;Cj6B4-g3S&?G_zKJPW_5lP`P?J6PmT(M|`-soOvj!?;SO`yM zJ+~AOY^etj`Efi*Pb%LWEA?_)Utt-b-Uo>hgi8|w#OUAtH0sb~HQB>=IRs0j%kh5~ z1h*>n3{qt5ac@J51lLwu*zNMs+u6mAPoMw1ZedLdb;e!ss?{R|Uu7~;&Ctd5rz$JU zr>~oW+M~JzgP4@L3S)8|=BGj1U9dV78@%-`eQ5Dg7J3CC(s_Wg zu2zk82UyR!&RXr;t^yKw+}K@QpGI1r41ZrWaBCDpP*py41+y|uSw4W2VUUa~zNcu} znzWn<_Ek{Q_QvcRJwMZ*$q_r80?h1)xk2QF_Ek>G7XrqNx@=iS*DTB7Jr2oMpAv)p zmM|bdWuA`}aGR~QKk!egDXNyBhXAy?yzNI2*p-r}vrHR*C_?VYXG)Yny1Xj6yDrt# z*u&_O9I@5%eZMvDifM0+0&@P{6uXMN;?(mPE0#c3h*gKvens6#FnJVOsf zjOl;Wfx~Q4e>#BR8EQR?@$o4S@%|tV&n0R>_SFHHPW0AK)<-T{gd)vZw{p{G4HLox zj;o*NBM`;)&lzl)CBLM;c3nIj?BR+sz+Pl3&7l!({QmmYMEP~~;(myXx(rI9Tjp!I zBToK`6+opEx$0VK{%5tUo*lUc27SLZ0!;?&J-LNs@Mb-I=c!s@oiGqdo)Baf9>o`n z+u^W&kUV7b@1fn#L*vP7&Xcw2k<(mm0uNUiwvGdr{A0>HGmspaF%u9NiTXnY0EPQA z{h0L)3K(}`G#m=PewUw+tO3_1xghLe>Ks(6ZJ`N68-=-`dDCD*&8H_os<2}jO;XMy}&bpG=o>cB>V7yr6u>@jpf4$J*5q;xD08^YVg_FKNL z2ax|E3XD>XBacte6K+jOw0B2OwC_;MCK)2)`+~eE3#!CQwezRtZ#)&{*Gk+WGdo~p z%7{}Xm(#nyf~PvMVr4c8q-3BOy`FLogzXS7D3v? zrosuRw5Sc~yL;Wo8uH*qlGc)xtHX&u*3Hu@k9_?)e};_gf*05?Hp$bnnizitW=nt) z1vC|mOR&7@B@0gYPO>PSF!-e`m?KDK;ESaw0lQ$-LKV@`C{g%_2HRl(A`fSyKLM43 z`n@{ZuL@uCI@bv+I~Wx0jXv|shR9K%{sr$T8EY)I6&uGlUcQMl0MVOQxrefd(~;ijn%Pn407fbMoIZ& zerFksmObQbmGItX6myFB`w>qUY zm*!X?4h^)p=D`7@-h4|~B4>2NG59y}mF4r&HDf>gppD}TPx|4LCAu>~jE`@{835*+!|i3mX)$sNy(D+q^QwpvoJ_#~vJ} z!ASGu0T&VM{+kOz@a!XZ3`L|;XE$UFKmG3s-;~Vcu=JXa4+6p`Gww@33Fo=iVYMSn z9F_D5TLD$1{sTWYC*w1pj4}=cS(s}WM%Tgq$uk~rizNeFi8(CoK)L1E5A`;Y+B#;ei$* z>QTjHm}Knn7OMqV`Z&|KVV`jsYh9f`J^4yIi5F|`*=;j2P8z0sg?pE2Rdu4@R7_q=jcb^%cDzWClA`m3TLD@PU@&WoJnR^-%R7XC6A~mmXQ3zE6*fQ(FGVbAUlh^vP z8J(FBxw*$FnUuC>R{&T3?Ivfg?QmyfZe1ahU`H?vomKG{+qwK5q|9OpBWu2P(SXk= z(q$#X45JXePir@&Suhz6n=7LTc|gaa!^T~brf=bS5-HgCgeWeO@=nL*_0ek3%AZO^@MPuyEf5f${V1Um*w26_U6zsmM(-<_xpR9Ss#PhzxPO2y9-}el1(`-nhfbF z#6L1^qfk^$kbeuGf4`(kCwT~S<5&HRd&H=$fmXl;>IW{*y z9z4aaPUL+UG^Z|#GO~M{$J3lDL5dG*=WaHL4$ACc znZdl~JgkkG<{PG_ZH%f>!UN7!yf(!pzqAR1NawXLr)ML4zZ*fGJ>9@SyuXB|_o_TU z#Snb;>gtRj=3aG3kV7aYh7Q+%gbb`3T}@K@io}`0Rul_i ztDvTnlB$7BO9XvRXCP_mp2dj&jmmuAbJ^U3ROsi{C`sLd{RtP4Z;oA?uMcpT9CBTc zxHX?OYMF$Mal+6BD(Ue>?trL``~t-XID!V+VD+S=hsSQ2G>^p)y+l<3`VVwqPOCyl zk+T9On2;U-rgQLBk>cCamrv$F+V^|J&v*3mV~A33t1UQ_mwy@dZ|oLJMJexyhWLx4^6FSyeNLBcRYwY)Y8Bl3j6IhhdnYa* zSDUZ*SZ6+rJmki)=Unn3I1b>7>U+QpVp)e&7>+%*=(iY4)>-hDz81w}e>Z2U-ixH( z)MnZSQLAFy1mBVoUyNV3;%L}{|HgeM27Sy1bp<46`zFu^+E z#wE8r7;hZ&N6@%EDEFm+Cy(`gWfCxTP(m_#8xDp@7+)|Tfkek@aTvhUry$?VAL6dJ zQZS(P>=jV}Bui@+UZ?`PvTvch%;jlgR#Cc450v~uoAB6Fpaug|FqYkGWi2E8fmnfq z57Z!K;%%ZA*m(42>a-J|6}ypQPLTkU<4^?@eR#@3(;V0I><88Jo&t- zER*~SGB7+H50;NB^&UY`k15H|#UKAehQTnUoH~|iWzo|`vxbfGXVr@86#dxu^MF1A z0+i>31~g|x!Qn%xD19mId4<)G4^r{_xJbJPpK0@wZdGYt4zbkHWTxNT^9Gell2j5v z6X3gFMPO~Wb-a;Qr9L#%1wSuoaE!GY&DGfpzn|wE*I>3oId;|r3k_}MysY+7tF#PD z(KP$EGv=|`Er{Se`tI(*klxnE6RGJkL7+Q=&7SnzOd?9Z3{-fGUfTjGJmth)S!Y)i z3AoAc@HW`8eR9$JJ5se?*tY74a!DSgFGlpN9J{V{%VU|dAm)w$4r};?4OO&b2iV#7 zqk)T-YSiHs_+oGqfU-(7=;kO@h=~A}=GuBEL3!F9F^teP8T((hYeQ=o-ec8M4hkV9 z!q$i`FoU-nqzxn>H?Gdq5(Ap;Jc3+{wvznG|6z0SyKCSgrT`S{ zRV>9hj{BZh{A{hL6zx{c$bH`Gy-^YN_IMqipCfisEkb5kXweRHjgC!pR0g8*<0+O#VGy>(dlUeD^h;?*t=O87mY{$(LqbdX#|#JD%wUG2sEn5p$% znbNeYGtMT@@v*LZ?_K`vPQWn&sQl^Q<@y3s8hzVpVvK_%TvIxFuZAMAj=D`5q1%q6 z5O`j&)x}f82nlfdR}zP#n~6f>EKL zWBLy}{i_XFi9;IJE*Irf4YWq=kFfLGI~||jwQdt29c$vVgP(+DR56YyZ`&C}tnZI1 zU2s-EtN}NPrv~vSZ53e$3-FsQ7&cFK3wh2dPm~Wi(;H~@)T($M!#1&9a*-;djs>vkFQ0|2?9}@cfkQhpQ!KAfM8=LRD8X?@H)qe|{3cy}#4oS9whaYoB z6@2fC{uJBs`u)wP#H1SIn4b#*gfqiJkKYSqkQ_aotXqs!OAs$sC@zsDEt@(EV@*7OCkjnNJjt?`Yt4_}in)gY01UawUaF#u;e zIRyu30ew9LKa#le(S_w%_&s-W%SMR0(Metm+{N9?V29LjwJ_iF97?4S4}xVrktTk| z4S>WA>Qrh==6puRckDUGO6yMeN}JzUj7gIrse1`LnyP65w1k% zt%tllmho|RzS?ZWn;Pxv{1u}^_gAT8Ok@9giVr*L-$4tKJB8ZjOv0c3lpgDaAL($_ z&@e~#DqVGP!BU`(@WTckmK7q(@XL@$XcL0uo1^bs72AUvrsELrlSHy3Q)a zaJSiKUk?vRTWb`VVi-=i3886U%*_akTLJQLQF72h6%~%{HTTw7zi)MBjWS3BZXT$|;ao7!Zyf zXKVZQhpeXT0}wc)l1y40U>PDZVsRA%rbC%O+S6GVJsvRwr|;38FW~1^MEL$`RBQ;t zv7r`EgXgaNgBul)+c#k$nCqisR;hkS%CgkrCv~jm~s*~*j@NgBp}gE zO<{BPk^A>~u1cNJh90A*iu$o-`@B#xst)dXH8kuHOyWr5;T0DS_e__JN2x4;r7Qjq zH)mo)Oo%=zz(_oAm3IY}pv8mX5=AjX9T7q+sh21rPhy%i5IBKjp6kQ+lV5dcbJ5x= zRi|0~Qe$k{K4beHH^)9DP8xx#Ah3!K(Wf$SbQpyNLUuttEW2z{KUxxW=1DBq=mm49 z;KZjRe3Aps!5em9S#&e9p5n_k$pv1Ne?}A}?2I>m?Ud&~VVOn9eGb8?d`p!qJFs#q zg2;vXA`=1#sk42iRO0t>=fNU0x&j@J@Bo8B&{|zfNxEM9KG3Iw*-z*SQKMvXYpB+H zDuz=X*bY`u#5R)Q!a$g*5`%pGJVgLVZWlI?BW~tD!}+q>qJoGyruWuCpB7v+#VW? z7$8lcd;)#OsK8O>mT^I4B&O&1FY?3n7Wu`uoW)Tr5&SYe$|u)P)j5olmPaKP#^8Vl z*~bp``Jb)!`gU9;$J13JZCS}?Q+Z97yF8~?JlB=|kdn#y)LI)4)QQXFb2vUwiz>Y3 zCVT81Z62Si;@$*Z1X)K*CZ`rduiWS`%}qPzjuwn-jIh=Z4Y^Kl_8Xa!QvL?}Y$Sda zq8`DzdE2|;aVy$v$$Ij(<+``}2(Xs}DyUAzP{++o0PTBHNrZeC#+CszNx`oBi4Z!kne!z0AuQdqd+0E64=NSY!f0kj$;&RqfJ~tYCL)C`f)n2yu z`4x0$A04Q;5-Kk9(MIxyT#om>cyve!HT3!d<~7`eaf6~U$cAVgMWPEd@Dcv5F<6;L zYVi!^5U(Zk@H=cf8F5R+V(hp~mi+b`agVSAQ{@yW}%DsfWMABlh`6`A=xEsvTcXGW2Smx3>RssGb zi=H64Wdxm+4!eo1`Eu3c*wgT$4b>m6!Hv z?)4no)K`>A<$Cj`qRzgU66e02e0nH<9NhU%f{|xn;#&7RDJ8ItBG=LS+Lw`iJQcM< zhczMvw_m<-EZTs-!Qqb|W34&S%o>&KMyi3h^gP!f{_sJ|(%s!a0yD~yTyE3?2z4Kx zHYiEKnbW5cbz3+L43_%^RsKxQEh0vp!vvE;n^gK;$ zyZ%B5-sElt$xj)XPI5Zpw$hChP~3r?$mI?=XA*rZ%+n$LYeY@9jb!$F9TYM?Vg`uY4^?92Ng7)9W&H`H+Qtj^^z0nB6H0>m;L0IEv zFXUCjr<>d5ylsy=BX^?YS3C)yx9>1;wA_(L>A;%mBULWPF%GM)h%ZeVgKK70QMjEa zas7T(2=Ev(K}o?>aqF$V+=^-*^Uw#1Dd4B_CLyI)cqGzBUZ6yh{IL(_n<=z&i4S5J z`Ut)`kq5M+VH+8#wsoTp7vx7&7Gzp%G<(dS&7St4)hP_QGVkIg)JAswJIL|-lyvI2 z-bz*hJ|lG?6rn}M5{(c0Y&C_5zDM2MsDwXUU{@n}I%amxthWa@ExSgwANJa(w0kk` z__IA6Vg$4&j<_j{LzgCwAw#`^!&O;0t)CmcJs9HpO70&$8jb@pY}R6R4bugFBseN< zuWN@-2%=0A)BG6ZOJt>V^t36J(4E=cuE_KUP2(y1(uhsTPDWrk>Q2OvK^M$p9?q`$ z6Q~C?p+EoW7sGO>0ixv{(09_2rZvNBw^v9RHa_vZnOR(eerW)V_!XEnU?@bu(k%fe;YL>*;=zjGYCQixOLeDg!!hzbk782Uo{8Jb z3b7LK72v^mwe(ltbKKILHVp`-HC$L1Isw$VIS6U_M)Jr;w+;a1;z3f;)AA&f!sY6g zJibU%9r^N2Fo%k3`UbOg45h5y#EB;@zDSp)g7_@mV5( z;;QcHco1BMoS=m>zY_NM-7&*fJ^`&yY)yN(r@bzWG;0|d2aAF3DYKxs<$n=;%;dMq z)Nj#M=rl7&W#I}F$cZt1Ae~TpfQ({GY#HULH-gLKT$#yHc+sI4(8$XQ3 z#wt22TiG{aqowKU2CF;b6_B(|l2ot{6UZQ890z~deWaFs5{`wC9q#%6GvfK=`|gsi zhF$F7Ja0)`HbCuBJvs&J)WuIJA(H=7f7j_%U?njQPEBM7G}H!*9l|4Ab{G#6=~q9Eqco27b^w-SIQxKPyC5)J@GwbwWC34zOO=f{+`Qz zfj7JM);gRnFqJ_k?wU+o6d*II*;*G!n-UV}ah<4%t&uV^EosL$4Ppdl&rw~TD@l4A z;_LO^eyQa+F@XY0`Rn?+c?w!J{vI0oUoGV4$NegNyR;&{7Bbhsr71NOCt6ifN zfXHK`B~nr;uq){KCPImS_}HtzG?Ag*AkYQf_8~V^B1v=S-%l^la90rJzFCh$b(9T$ z_3q+gX^hDP_(^$VsOidcY+_{jEmP!ybKQm;erD);;RIjy{?-jBY(@(bvvac}MKtw$vd-L`$N9G9GG4H9t*5*!(1H(~eb7m&N6wo29&vbLo|r8jv9JEo3c(>1@ij6?PNg>bXy zi}=rHTse~V*a%dw6iYe^AFJaqSUAF=2R}ZyuhC#zWuA;Jnc(xoPHfjIUg>du+NX>*RV1|_;uue)&0Kx*)&#) zJkMh8;{cY;a};uTy+Mjz3{rrqnVb>)g;br>mLO2FZPT`G+qP|6m9}l$wr!)*wr$(i zt-hnrL;phTr#)lET%GF1_IpE-tntdU+Nfl?yIxFFo=%ap=|u-(vybYlWQb}MKG%KW z@c(Ea=r&5$l#vqi;fF!1UgelCIjhmw=smP%8$Yt$x*DfXgkRaHZs4f#;+2q=QlYDs>Ap`Tg{Y!Zos#Y;2R&m8o0l5NxGdyen8 zXE)$AJ&kIMDJE*EJL)TTJ7to!UKoxEM=GEJf!dWX9w~M$Pg3pC1eM04wzZigslRp} z%O#u$9WMJbI6OzVtsl;DK5e7y9h>NXo#J8l_Bytyk&wg}D$CZEECdhtV#;y_tuR`glDXv#P*M#L%u#$W*Ul zF|QT^+^{tBtP%(0UyZD%kB!9H*t?$Kc+Vt*w3-3G*j?+;CbnB8k)u!Jo07{N;nsLf z|EUo0f8C<2kkk_J;MWBwjtmxMDErd(8SnUXS@WMAzKRUb(y`(P8stAWMa_Cp9JmIM^XO_UxSykshj8R^fz$c)+O8Q%^x>Nxr+;(3su)_ zF&<0XHy%96+_~`Egar+6t&^TUK29oVB^{_%ryl`RcVF*ef<|5bcAwc5%2J-`@Gu+z z`o}bnZdDl&mAbCrz*`qa& z!Q*eoDYw@f9wClhr`Z03ZvyZWO+kA9^iV?*57aK|PgxNG0G9o)w9A9RJ4A>_miO*q z?v>~BHx|ZwRqr)~Lz-Sw)K0-thlUcU%2Hm1wAWf}2mFpZ!dA$nDT^l)A3c!(NhKq%x@uZjaq|8_(YU9zzsL2pOG7UEtSKz05gGov z!8dqjKvj*XcST?FfG~hG?$P84Q_)WgT2-XM#jiB!R+x zgqIhOiuBaEJhYM_LvAz~)yV?K0j+INF&pZ{`Z83SJkW&*K5vS|zv1q0I`$es3V*Pj zH5~@i?0gsUvfhmj76R>NGT;0GLVlTAw@2ubmlaS5O3()W?#qcghl>7pwSz;1TnUeM zl1(AKA#x`2(7_yHvXJXpaJtG?8lP#y@mcf6QhTAG?gX&o^DV}9!WQRt!sRFiXoIdY zxA9hhd0d7 zk;t?knz47tBJN8z1?~Eh-TM4<_wM9ZsnjOaect#tKH*#abPn}Xm1F5Q2?;v zixlLRus=PQrRgpMv0A^qfzQFcI|MBHmsboIZy(OJRGvbw)>aQtexEbn_gv54v-5>k ziRs|eUs!pR-!c3&T|ZJsd|oZ1J#EBfAhM99fQRgXWsbEQcl%PO)qK%2i>pn+w$B`i zKY#2w0}WE|d)bswvdQ}apLlL1;Z@F?aLy3@7hm-(=`J&2;aJ7H)6kXm;6(RcWW`zC zV0$h__Yga6X7CIq2tddCiWI>pY30++=1f&dm>x{nVo%ERll-Dw_ycS0f2-n+sPh`3n&EUp;13IK92Qzm3l|0$?)eks1ZGv5As&H6QoVt* zvDf#fn=lrTFQHT34GFXA;B2|Zev78!{wZYj2(0TD0s+P{KZ23geJp%rDMM=Cc&~yM z*^$zo@7lroAnZb{8tv6Kc+Xvv+R18SYk65;dGKVCzb(iu9d)93^Df0NAs{GOjlLmrAdldiK|U!z_My*qXAspSc{?vQ9Zr-Sbr{ z^pHyNEl%N>+#3PIpnov7{oCz%B%LxhIOnB5A@fKryB-uT_j4#Z5QurP{;e{v z-|PC%;C+xU-zom7^R7nT#Jj_!KZ!v^A&|BQDNwWSO%o80 zLl1J^^#Lx|ZaOOY2ltUOhxM^OABtDI@IpU`8n;%3J1c+?P$^Hj&JnvW#)EQHiC+(0 zYCicUSoU|Q)-A(8K$B$r2hhhR9e~(mP1{EbbsXmePyI%w=DN6@rW6as4s+l5Ad1{g zKQU>Lm1&ZNmO7uf@>t6IM!^~az;(x{=D9Fr{XEbdskSp{rAlu=CJtHSMtHVpR!gRo zg__ZqN8c!v9kxD%`p93G){p&AaBO#6=#K=ZdQ#z5#b3$*f^8RkxJmP3Uv)~#OQ{Jn zCBR~rPDj%tWm$Cq>{J~Jwzomo*1N^R@stU5U_2c2zjed-%} zim$xy!$-?VBd*AcNJ>Ag-0}^0Ag^k?vg(e+;6@>c`C3vwj4pIERNMxW1f_EM5_w3a zkRHet86cCn)wwO<9-=GTp5W!SzZhT4{M~@*;Ve$K>~%^#lpSz~m|gBFe_HgcMjwT? zf9rl2N5T2@Vqg*+)&xk>fIv@ax6L8jha^B#S(`U${Ej4Mhapdst_fj7dNA&r=`I9v z`N$(9d{|GyT3fK=7~{+PV)JElhP``4T&grlol3cc&O{pD+5fIA5u=aLfKG!7;5qAA zq&0spgJk^%Dm=ctv1uI_&?~FGL|}bMR+{kGz?g>RoEbUB`kg(Hp_buJaZVGy-puS_zJ49dC-cz>(+O@)mZ+?Q4B`jd4Q5#0kndJyp|HQ)wR z;hWw|q6HX=-#tG4PR^icDjD$v`YjK(I^Jcv*axb#Y(9Cvc73)SjhB@GkeabQsu+fJ z*X7F3JG3Q$gtmmI#}%OjnHuLlD|__ik9)(XQw_K+ORDKzmsga#uJVyLZtxlT=NX_^ zvuKcU5^dE?JKC7KJ!Mm%)`0lR==M+-?&;7>VR`A8w5(k9+@Pi!VKAI#8|uN+WNXe* z>|afht!!tf7KCKucO(|BkDy~6GC;0G0%2C3nC4rGpA zl(4QtWY9>B965hf!`kXv;*5Jf0JeskUp$n~^dSo6O zt&ZP77e6oIM$eOiswZ)|tQy=cZ=}v?c1Vp(2!j~b z02BAW1tVAB3QC?TE_r#!s9R)iGSJ%TyN1E!@bbC#u7(RB&;`0n|=ll82JRQLnM(-f4(17g;ph zmU}Ac5dS7YdRW+PsS#6iI#+&reb7rA=^z(I$Do7ES1u_^ejpYMKsOi4SRk1|&J#%u zZ%)qGjw|a0MbC+muIgOUUPvEax9j)|BZxOH`&U>m{7b};)-(nfNG(Q*vEI@k%!Two z3*AP0ShTf7bsF4tmG^7`FSG=xgkyaRvcFMz#OQvv6P!g>qq6)8Vko!<{k<4iHwh zqarvaRH-Ts6unV(hQwVh@$@0JkvMsU^I~~oa~XFqR~5znwk^GZ_D$%d;MF0aq7Ax6 zN=pKO5)rPiKVaMNW-mQN;0HN(o$7Z)T@J$TNxSt;zOTPpMDO{u-RyJ1gu_sYL3E_I z>sO0{l!Zj}YVTaK{<}7vaDBuKiYeVU0?e(*s}Gc~A~w}b)!7V8CI?%nSRSrK9(;1m zvJ9G#;ez36roE2WB65inaSf$TSeWn&bg9KB?gFT<=m4_C8-lNp2GIVTyk}Hu{Z{{t z3el-qpbVsb`EXLN^ZIqWKAOGk?MYtPTaN27 zk=+wzhfehly~|*VZI(QDf29PM0td5-nv)a{#h>AR=SQBspw)-@PUoe-7Be!-c0m#l zyjt#+txHBPnE$gH6}#V-Hu&S{Tbl@)RgMBi5*ZiZwaUK>K-ZV`8wQjv(hpEc5}Lpf zxSD~fzbJ8WyjqTpM0-W=WjPWnd!8lK=YX^40anVhL5{>GjZ<;`VSWO*NcnMZhMRPT zuygk^QMGM3o{%0y zU>Hc3%G;wD0ig5Km9BEyGipXzei$oq+nAED%Xp@-;8R`vdW4|+8E4A-RscCrxdB=J zu^Q7=`CA0$y)Xa((t%)R)&Feb|GxlCVH4YT{=r^aQ1CfpJf6OmUPPuXH`pfp5R-$r z_o@xVK{}gQyALaEFn?oV=w8KJhfj;2-W6!4b);EZvS!}bIOZr^?ik&Nxa$Os)N!A+ zyNC@x(qE2E`WxDXrAg%S9g;zIU&n3k3<>?Ou8+P57?(tMBvrqncfBU;5?MPymsy5M z@{%q8O7>x*o-~_6t{JmR1!~nQLt^&MG-^oNjetlm$H}EKG7qhs68mru;>8@)TOkCw zmR|E&4KZT4uNQU*)#TC6obKY3Kp8>uf zN%Rb@qz_Ks1`Ah*#bHg6RgEjj+j(KsDkb|89QBWvgj(w@;#dR1>p9SiN7z5-e)OA96uc5GuIGdnY97N04Zvr;g@&m(UUbPRg=Vgz6 zeG>@fE&6H>BADMe^Asq|@R~s`;u8d`#i^~x>QqaWs8l;?1t;Y-i{KeVedJQ}mbw0Y zN&d3HgK@TEG_&8T?$&@ZV^PCjmV86Bn)eLRhmOp3GuMN%oz<=%^h@>EV|FNl<}fcV zc159b4|%C~>hgcq$=q&>=A8TP#r)}1?+yU6I_X?dxVq;foP|1Tx)5iY=_{Qm zp(7<6zQ`R;^4`MZu)_-XedVH1tlY8btXZ=2?G+e1-4WsIm&o59FH5;9w$kGZJ7)rB>d~{V#Lc_r#zDp zEIByTGf3J6y*!tpGWHg?IE^tupJ1x+1(`#)`%nY2euw6vI)2}~ z346)u9$~r6lTNRa*o0`8?c3x_6BiumUX|CYAc2tld-u{z0PFa%Qz{c&finQ<@K{n* zb=0txZtvKssgEEx^UyrfDDchW)F+&?ofbi-P2xm}HU$OT*l%3Ix&9rjOYxA5>76CS z-6KylQQvX3+DInhS!+I0O2<$HX1}w#C1hp{kvyfVZa!b1s+^Q$aa)V%M%rduQ6I*V73Y&>=A??u7_yW-8WxFB1nCwoJam<#9}!j$5D zpX0X?E3mrH7y2W10p^!4H4-ywJ?8<4z`FS0iSLHUCKkM?;ST+$R<^s`gd;sRAz_Nf zKuiX8cgFzUlc>quy@9oZ94vwMRF(9__CM*sM`ri_HIl80Qf$ArFBwPmMG#o+F+1WFP1Igp#h&EVo~IL? zy$i>&xFM%rxVlZ&Z$kb%M^*Nc(0RAX!cmpj)4kOovbw+$m1+5-nDn%Yirng}DN>rN z+f*G6ouTbtrDKliY4S}jH|j~>>z`)MY_+gSMkOz;bZ250{!&f?IAE- zAe&fVc7QizVY;Yy^N)}0i8*W0>viSq*cWmyzBJ-}0TTBtR=h!Y+!!G^1naqsrkw}M zgu$Xxye@kT9Au}UKED={rRNcex!Kf*RUTJ5en6NAc;18*WQ@fp8PtZ6M#g#w$D}I6 z##&loRC3fP=}c(-NMyI==D;YnB9(ukT18cUbk76H^rH;fafu*#f4F8&V1{vPX1A*x z)4F}@?pftleKx0q)I4_mcAH^kH$5t-m?2^4seW9PzkGX!ITqV#^Ux;<`qq8zC34pz z$=5W`avJ&>~H_@w~_zi0K1p|z%(_1eCQF~-RI z%;!Iy&&}yK!IW}x;qE37YKD>VaYdCMx#(YR!Lm34B+wUSCpcc$6oT)3)W5Z6RJ)8{>~L+M z__ioOq2c(7wpcVKWV!LZR+DVW{8X}*Jk+VMKar(A=0m8&S~XhsUj((!E2ck|7s;O; z5IU10dJERprGeMetvh^Q)|$eNq-${gHtuDaHgzFHuNge@N4^=eGGp z;9(ikI`S;*+;ttQPF8x6%^V)r11i6pLLY0wD)>NYtYwG>Fw7E1(UL!;`|pv#e$j4eow7+}tTL-+{3c;+h>N9iTN#^!+CCpQ4 zF2c?y_o^-#q8PV1JcM&`_5%dNzegZ7htkc53wBo2mQlvA7)+03B46RZb|p9tMBEWd zccS4>|L#liW^(i=7@W8rt8-&E&#s&7ps^6Yx2V}>L>lm5F_r8*lt5F`N-^{Ty^1&t z7m#vqnV?57%JxPb=bCeod}v!0c`ljk%K)XP^9vAPp@hnCEISdNxK4nahGYK&SF8#Y zmjIIStUTSm-0#$9C~_Bagtw~Ps+UH;=2NJe6=tH-{o(6~)v=|mn6CUPfZ1 z?i-DA`JD0ZSFQNa)Wxr|sIu=N=No)BhT5P)AMz&k1o%iS4Gqcm=u3EbXd~O;0K}#1 zmg7Jj;v+i^3W*g5ZpY&IW}|lX*nY#{7ABd>Ke;~K`S7`QqDPDXOA)m))0I0BaRqI| zP&$Mq+%K<*{9T*+Ur#;hI@@(G`jgu>TWsTi-hB8t*99eaLm>uMz}(#F?CEsmSL6M& z1FW5n8)Y+bMB%T#n6nUjj*sa*i(y3{Oy$6*E-QHSQ16QpUS?@QW!Ur}+g%cRnak(i z%hVG6H|&Pl(n%@y!85^yVj8Fc?c}uHA6?~}%&&tCp zR7L*TW76OVC1oFr1z5OSV;<@G2UdK?4Cm8d7>s@G@^1B=zU%sLTbpNC?w?|HHWw3+ zggfXlq|bys57u1EaG2J5TX|2^kKt$4DwKu6p4!v|nfN_d4i`tLB3KNr&E2VprW`$h z6VvW<*OhXAm{vcNQ{g@DZ%PJOkIY^|W)rOpNj=fny@=Z}(Dr-nl!dQ=mfIB-&s#qE zfJ^UshEFmu(6!Ar6aaquR`rsDt3T1w0#$F2&;nm*v%K2fLEKKXzfMnnfZVqtr3Xf88k0+Hd2&KG0l>3Whs$8Ntd`B%Y1sdXz%^i|L)|P zgfqmmla(6NpUe0)ar`=_2JmCxDAT&Az#NoXq$VgP7V+UxS*4P)h{U`^8baAvzB3F0 zLTd^>GyhbElaC8w3yUcp$uLas6F(hdZ!mGwnWegN(8$xks$2G-ujMZV@xjz`F$F!<1y^+5V|=^W$;cJR z=ZqnD#hN!h-t7H#m(u|vt%jy9kpuq>6VOq2M9hWgD&Ja&4duJ4{~^S7EBoQj@o z(fKsgpD`7gvJ(*X=HC?6Z+vT!c{+cS5!Xl;t*gDHD(JV@(iLNW@K|4X` ztYgY9>cl=?* z0wznD*(lAYm4ax_SGUSSH7BT@1Vd0U?OLSh+(z)!YcIcxc>z@^6RHh!-{lkL)7pWe z1yEAibJz=GmmTD`5@Z4=C;1j*OIM3%+HCQ*6U4WPssDVh;(W;CN~KhfvSp(PVG_N1 z)3$QlIE6ML?@^gQ>6GPGL_xe_^d$S$4!HqW)n^-joeJrb4wKm}YCFuph!Z4VtmeTz zQ-IdvHM%&A*o77u8Q7(sF1`y#7NrQS++=10Q;Vd2V+UG*an11aDBEDid~cfr&3h?` zFPL|%+Iz6TYNuYa5xs6hpMpF+Rl{#rA>-2H(^Rf_|WpMtPi0Yxnif3x)SBR(f-5*SZqs5YPq6uANjE^V#N~v#3GU-HSiV3Mz#B} zvEs%JdG0b0aOw%Rx9E$R&2P46$1V3^`$~07EAgSZ3Aq!@@h>#)jzmZroO8SyknR%P zQLfE#g5fAX8kz7^@d8Vy29Lwkti2%}6g9h{&>OlQVDf!R6gM@;>Oyh=#A}gTJkV zGKM~cVMQk%2OY|tEDNQy-&)ml13@_lxg8p{cR%4Zc#feA+&Nk_i-S~xI#19DVo>(Mv2W_$XdTm?D{%*D7>{rW2D!o7we+vKISfp z{tU{I&4%UXx5S=;2E1YB^)`-U%ORg3V2yiQzlLCRV`NPrb7>;A;2w(e)R+qMD+-ss z`_u{d7w2fPGEfe~4Bmwn3g>z^CxPakzBjawhS#3_$Lk-1FM)@9)0}_^WB5oUCftQq z?S6%_(-AzL@bCL+Gj3=3B;Xv7!Vt%%L@pWYw-uuew+yYd2bmB7x0GIIN@DsP6C%D_ z1_ap)CSiYP?rPvE_i>sNr|UE!pYAb<%o@EbLoi=23PK%NDt@p-0suYyxw9krF+sRt ziyiaX&K$n5&(2P+_ak<&UZO7@V7 z9A=qO8SPqGE}qc=f}v2sx9?ZTp@3e`R5I6;`;%YIVf?Qduw07qL9my%-*?HxbY><8 z;_L>K)2c70nLK6bnoKpn}QG2LX9t0@B}~^Rq|1 z6*)nkP0@w6q5k|$5Occ?vAmVznZ;U^U1_Vg$&G4X zE=)%F2T`2_bI1R?YJhT^pUYh0`;u4i+ZxigO88frtFy*oMYUzdX?e@A`7t^M9%rkz zn4kzCbzj!4@G!I3$CSYodgfCfw&)#f2qeHJd&%9L5i4wh>JMV%j8?q3A*?X7PGyty z7C9o&%JB;}^d2Rf;lZ8PpRsyCVf-(5@LAk`bf;~Cg5_Acc)RIpYL<3hqGSLH821KC z2v1|_R!6F26-r$Ll~0s8eAi{uULq3o4uKqz3+xR1Gin^xY1T~~P|Q(dMmcCHAWzGk z!l&4;y0BZc3c*{!5n5)$Yk$G*d*v$TF=kB-$&W`k@xlshS2zQxZbV?n(9(MtcK2vz z>dkGNZ=k)OXNf`Wt}L&jTS^sSc+=7*u2)i#rwH6BC`etll&_&mnn&XOrxN;)$WQmb z#-49=5BkYr$ri5NY`o7P=K2BZzf{6Eos^Bu@y_jv!^GR?ME<#_zFCtY0g+F}OAM6F z?%+rm6`hTNI5hvp4&VZqd-fl84Q|OYPiE!oX=jc07-L`C=4VdG$+G<<`o!?931^n;0dW%3}N9d#eNHUi{znUV6^X_Z4XN^pM&yVAo|g zlH@)I2q{XK#oWw*1aV-eezs5pRA<$diwg-@&NS9o+I<~*u{WKSUd}n7%xm(r#^F>v zSIJcCLpJhv_#z40n9iCzBjmkN>7`1vEZh5Zqy6G3CK7?@^9RkZ(2Q&d`@Og*(X*#? zhM5xvDn>K^(Y1HDBgrqinR=!NK_Iic`J)0klAisQHjS@me0v(3$Uw zNHC{%+vo)zSra0lkidfad2UyWT|#Ar%BS=A<;!OvTYHN?n+P0=+Vv4^^ffDaW3B(L z5IX@Pd8udz9NF{$-mu!#iMTZc=$hIue4x-Do+Q=@&|J;U>NW?i${D|6`7 z33|GA`7bd0RHB3*Ieb9w7Q;n*oL%gEX@CR@4oW091XfPe+u_VJNctD;V%fv35L4h4 zavKRGHToZHRi8@J2)RBhYD4`YBFm;MEe>~ z2QGMxtXtcXCH9UhbdL3G;#Z8Z(+)q0*Vy#bOq@gdK=8Epnq^m?@Ugd}GGgfq&$JlI zp)_a56r)U-hs-0F_Hni9dh6F57cPfz5r()!6J{I2AAZsW;4I?47wqz!5XpM7wCyp4De@1b9+CA z=PHOQOERE@aVR&`MVXnezd%&flx19+Iv_938%rHofkFDMaLbSp$K&7j*1b!hY}5^4 z*|+zZ1AsKp8!*rK^&Xv%jrY=%S@z_T=xm#^U-5W_k!}txVD;cWBot@l5VbOgq&bcT zP0~^{U!jqN0*v->wPz)eO7Qq%VPkqSzky>|Kkl%-GdcI`-N(DDHFEm*+O^reY&GKP zzamxONSEjkcK=*%*^`M3Sia|HLWnM1VT_zLfL~4CBXRj8c|AW>OD$bHcM6enuG?Vf zN`MJ&s7{2;^xa^+&ilM$vPJ|I&3SL^M#a{BbDFnTD`#Ktyu`o*EtT3g3rf-zP4 zAtQ~J`%-#2aj%0fOQ1k^mq|< zgEjIa)vYfssJbg0i#s)}`<1yg_Q0rq%x~Ed78GuhJD41EGPq2l^U@BxUa2 zhi6L9iI(85TnzMsd$(!2Ye>Qy9@@5i@c|%E3wGEIdQ(W6fQNt@;@k$kqZ5#z<^U8( z;5#4D+Zr{3<;qfqoXI-Ls#Aa+uXz&4a8UeVY+B+j3_&c@EpF2Ku|qWo@cg#W$5i~2 z9X~iXHf<9^!&M!07cP&!YE34yxs5l(?)?g{tlut$S#OcA&+yJkkt_X&vpFz1d1XxP zJv@8clf#GcV8lp|G5rGP$cF*!3~1kj_N_raltS1AwWuxlEYMd>dy2b9yi*G1O$xw` z{2CP)9@%JEalZJSR9vs#eYa31_S$r!;KkzJE2fGC?3*^s>}~^&AfbIirc`i+7EoPr zT_P3lkkO-6eQ832jkC3qXuOl$M|K~S=?@&hb8U#Fjn|o6=CnDDx6MZCZ=R6F(5t2w zq3KSvTp7Z=MY8J#1?895y{=qOt@Y3M!Q>w8us?Kjdq~jWF=0Z<|vf^!$zmZrHJL;~d$Qrw# zHt!b$`-P3}7l1Pda|o<=-7Wbn(ov%)#0nqdwzX^V65T8ejP5V! zYBkwIJcl_+b8%fkpg%<-eJC`Sfd#Y5;ht6OPm#+zc4>8)Q%>}i?44|i6^KPw&BwE1+dZbRo-a$5kGLhblERrr#4DiJEY+n=A$wuLwsdV_ zf56m;o0WQW@!9c8L)R52#c9SI;^Lv0L|!-COCy;Ry~d>6#AcM@c+;8QsLNE%Jp>=V zNXis$im97PaI52r749k_%0K+xVozX0?**2DW;aY8HKKh8uV(Y)J7!`|aKG|*lLili zKzcR`W}q3hMp(-&pd`-ttzG)-PXtYtAxLZlAL9D17bTj3TH@QgXmL*o+?ap^hbIB5 zJ`s5*&IxeCN;MLXY{f<*2Tt+7-S`(uj;o=OUPI0Djc)E}+gU#+>I6EgA|OK5Y^#7J-U4L0KYIUcUYHTY+IZ~TZOHci_}%%%0`Zh?7er}5>bsY zYVL?(!oBX}0k0xId-F)|B~nUKz!;V7!!6OQl+N(hfZm%WAHkxbtj^4nUeqzGcFgG< z&(vG5RKtdTo0;mM@tRWjh*sOizcIp3QG^QlCyjIn(wuu?@9WK<#XryNX^+!)0_a}S zat^)OsTZubVXI+((k+Ka8aXraYi4#6OIpfB;}q(3tcW$obL&h*uB@{&(7<|mZhY+h zf@rR}qNyo3Z^(P6M)vB1wmrPmDowK}dQUqpN>1QKh3YA#u``%5H>+bZ9rh$IowF8) zfe{~oO9Gf4xVU~0(54nd?I$wpO&zB9>ho?B=MP@|`yHyZz7%vQg#z>Tsjw-XE#&nY zd&H@wLT-j0UOxsTXzl2R_eXKXKeFQhs>d};Et-l)(C8VBdb6_J1^8U0Km~5*mjmqI zpTO0PsLttqK~vM{6@0?$`uNk-Hcd_oZm)<^uX>-zU;Yr8qxE_l$N&M`#t(!{>>})G zdA7l#RlZ;qCXg53l`8pG*UN;u$VIRN10t&GaP)W}nRpfL6&HRKQEt&&-FX0mWt)g( z7Xq&w5Ge$IvpX1?!y!80QfZPLmYIpP zIESR{CJ=6Q{2tX0N?lr9PMmF;J{R6BEdgvL=%aMcp?%MC>-UdIWL0AtbI^(iOaV!Q zJz)nhcT7d9X~a;O=pzEuIYjdj)I4Bx!RS}H3o1Qw##^QP#nr{Pt2a95CtgWQ$F3Mz zS?kaYGU+AI3d*6v2*u8}NZw+D0s<$4*2R^#n=L?oasm!^TyV-5pyfr){#wm(?2OAdp(@c9HlG#>98CTFuZvpuli%a5Z04X zf%Yv7NGbt;OSzGItA>^jRWDZUom#r4{qb03V821z(+*jb1Zx5B{yuhfTGkGOVEo7H zPPtPLj=q-VW7x}9Z5c0Fdzjq9VamB<#tx^n)rvCuQ#AQ^jMOfURAd&*VZ^v;WLE@+@*aBIMZ4M~IDwJg%jBY!m9E8m}-)3B>m z4B_Cf+V;(3npO8_$)`m934h1GfMBhW8l%hY)e88%e_7$PR54CDo|&F%d%6M*%hyFv z0BTqxIRh`i=1VN1v^iZUSDDorWLDs28xW$eixNovFDlP$0jj^#-vn}44Sj=Oz44GB zPyC#QFS5g4obrr!sd6SNpGt9nTXbj}nyaDS_QTNKYG*~XcTRz4LV^r8V0{(X_$z_E zD2qJjD3A>xpkDJ|KjL2ILQL?vP-Zj@dD+vF^VoxOs-z)i^LI9ZA$}W&o#arvAIPL~ zvwhaKj*$K`1^0^h5BmiYQVUf>`-|GV)IGJB$@qp~tG8A_S*`{PqcAYNK3mSZ1m$-+h ziLs03d>fUnH{)GrNSF>`T$|g@7KLf1%fR&6-A+*zC!KVS@5jEWPL|tteLEjoe?yaC z9m#LQ3{Gh~Mj5CFK?Z4XR%zLod&?wf%s+*81c(Q@3G-rE3o#)C9FX*f!=5-Ns>JJ< zSbG12^!?gCrABguj@{03j1$;J^F9S_mpg?E-$hK=R z0&aMhBHr0i%_YPosX|)rjP-P1>tF>h|kZ4TBRK(nvh_yo498j+U`ERl+c*Y?(h(} z668b&JyswcTSTu9hP>05VZV}kV`Vbq7b!o{-emdh_{R#7)H6xV2I5md5k2M=SA$QLQsygJ3T)Q<{+g}+6@!~dKAyq~IqxW*|wIjr%>Ooe=jrkhq~P%Z0xa09(X|3o=!>is{# zL4CkHn*YETkmL*Ig5UL^ov$NOeEH3`L#ZG0J^?Nu3BOmIuW*0M1O&pv^AE61m)+P5 z`3 zYhV2?W?OBn9GdA`nNsvTnh_zB<`sbG8lOCRreVSR0J`{L141gEX@Zf;ho}&}PZIhL za&F)=FZp^}CE4he-eI4*MVMyUCWk+f@`NvkQ*ZU@WzS$DtPHPVfTA!}b(Uv8A+b9! zy%aCR>06iWioHA{3~2Pa~jMS>sx1 zbxYSKte{-QN#rT!a(|QeGEpphix!~kzmebbCLhkX2MdoM0!WbmjTk^0Fpus(mOV#Rx#$DkPV8dn&4AR1@MlY_*;d`HJqabQM0~u4(zKDx(dnuSdOv#~<(*%%BvXTYNepq1hFgzT-c6HuIc&)eG-A8HScL zY+xH+4m$)SeV*9mU1DjM&O~aa1Qz#ACZw0MM6p-|nCN@VK{#6w;0rPYE#it(!d={i0QK zyB(k%LZ*JR@8@+4%NFiTmm_#5+}4h4<&glbRB+D#!BPlhyRa%NnX>9`CqR1yFw-uF`?Tv zn8i)P1+!4!o&yjK+!8b%Y-O!BIcxT*F6AH4NBEsa?Y`Ft>iRi_|PB7~*$f{rrd|40np4qF1ubn-}_I_m$ zgXYPJ<3ef~E|sj$siI9ThAeh12UL7T3Cb!}MyQjUC=vFwZ=!RcS*>UEqR;}JK`bOw zAxTI`Vf{i!y{pxYs3$R^`NkFkZ<#dVq*7<+avlQtiH_Ap#0yI0gL8GdpKASzc2UGk zom0Xc4DVS-zSUXu``J#&3>;!lOA?8`kXUBqBqO4tk*$4s-6yhT0GK4JDJmyP zeH|1^Kv_OIZa(n)kvBPqgtm{RnC_zs-28QG_cxM<-9BFO^vNehMY=295@*Y%-A@1! zZCNavbklMV1|}AE>WMl}saI$rvdb+cDsVSs`=u4VkF`NtH|>X0svAaI7S1i^&LLb$ z-+ib_H<{1xLX;oC^g)P%P8Uxa-u7)UtUP(r$kpPmAW`;38>O5*Be-*ic*K@${7HL- z{(M}@X-rjG52R*auKNuzQ(@t&0c3S%V?ed#mU6xJkiCKEDwpJTbRN{wl=^C7;sPK#5 zU@_8)0>O=p60vpEuv24I0KGzJssNpftvvMU6vx^pt#P8{21o`xUCoDW6qjSZWA#77 zi8vXo%{H01&^rcdWISSx0VjhSo9W%8iYB2)Qhz|urS?7WP+SnO0sJLf+`0OY*E+7J zxd)QcS^+X|l|H;&j*7d0ZTv!cHCU8D$|>ibq}~as-NfK=>*rYIT?7XP zUcYj(i_JB)~(-y>Fvft|f?r>h3v83X;d~nKG7ViNpO zxUYmJxNZMrP@OxW$iR7RDRXh}>=^xJB6WE7T>%#3nZn?0SaMd8Yr`gYrRECG{&g{( zNMVl=+h6OPwXNvtVZW!&rrW1lso!%wQhs1PMEnJSS825whn9a5mABcCi$mI#JQI^> z0O5#N+|E-!Y`laUk-`h4rrBOO=t2C;Xr?1C_vdq#EvoNcKG?dq?lv&xZ}RQO`q6uA|2S#+0W&?xm4l_;saXL}=`vTocnUw5}x#8*cX z%U-{ZVmeVXYyg5M< zC?~7+ODEY+005WsRN(Np%>Lp3yr8syVMvA@54`>}KlT?gx$KAlcQnwXre=mnsLF{*?Y z|2=IfI|#Tft4yiKv#>B(r20$iDePEXeovcsIvL`C|6+BoQ4aIz>N9&rPOKA)W~40(b1;F z#+`+8qGL^N$7Vlbw9g|$fM1{S%ovXe&%@Bk| z-h(XyW?`V`5F;!oOPqZV6nJ7wFh)UIoDM&}G)?2HU2pnWRD!6BbR%(8YFvsdH3dBo zfu$MYv9r#z<}!oWOMm)1bi%HnGD|W!hSeU;_-TOk?Ub>|u00c9?kg9Fyr@>rT~na( z=*nAkDC2U@t<4-#7F4I)Ejqt;o*MTLIGz~@?0j}~>=Tq>YFt@nhFT`S@uH2E3Rhe! zPP9B0RKodT^RKwycX{@U8CClmUn=lVC#u!T(`6$c0VVzg3=U#lstHR9a@asf0-0<)rQA3!mW=?yQAfSPGDtes8; zSKXNuGIWe)QL!`%sB@tdk1{?4?g6!tou*!cargZ31Yz%?>G_;r1heL;$4IBr@Hk8z z14Y37XZz?>tJHoH>uj?@D(948dL0U%NX>(?slT3fL8$oQIK6Hn(-YuunTAnD=cLxy z913U8+}#ERDqtCsv|&sBDYZJVID*6R56bJPr6e3EMv;kxmG@Q0%9*1D8v&4AT3%42+LS0mekK<_@=zbuT#2pa zQ!HIKV}56HqlRPWxF>KCrtRqXqSXcRH!`s5U~odsWS3-2;%w~i{u zTLCtru4xh$?~TNcSx$;@6SC9jow5U{{Ul3s7+S9gP*%l`f#u(U7ek~1C9EEJ7a|e& zCP~KYa*R6F4aq0@x9lI33=V_M@2IlSZV3Fb`|B&MjWjyken@Af?oidD<-D|Luca*5 zg?wzR{D4St;3msTruQC58d)$$Tq5WJ%VdC{5Kxo{kR~NXtir-(VH$4-eximp1PH4LdzO>jtksQwWmeSq%^~PG&jmg+ zv*jxPx+8ii)E$*d%NMnl8GpsO#vF$8ka7eLF07zhi_a4Nt*Cq>k~U|?K&A)hF0t|Q zTEbJ#W(PVY`1T3U%hyGr=k4<^xp;t=4E;44u|)#O_&HzU%A#7H$Nj(@q5gTqJEitT z?d*nT(U9TI;4bYaP?VK92~{AvkUt%2BX%?j7f21S)jKPU+x-CB9@WPzm#GjXX6gqu zft_!Hf~sejeMbiO(qV@Q#M(zy`N#feeeRLhIKCZT06iF+udURug&J>DN=})G4fzZD zSXTNZ4t`ohBcBq(Z5M$aA*4{DZ@DCRg1&m;a*=T5yAJYH^)!uU>6*-$kv4$@#jB#H z@4$j_*!|tO0Rn-U%A5I@_owXH<+#9UMB+wQFk?R|0g^^q-{bjJc{=~gz$lc*tO7nm z2mEiP>7DIPXNsJpSn344=u8R`IZzygw&(5>IZqoaYw$piCO9?2-hC?!e0TaWeQwiD z$Am-O!V+E?*NJq^7n+fPf~7Rssdu;Xf|fh?s(E{+ciymDm#^q?11`+ZsHh8%JmE%@ zfQuAE?sBs>)>4&F#F^HEAy-kvneMY+NERRlz6R}BH6(shYJU880k_CraNpWW5b^*w2jSs0D&DMP_j@L!@FiU1UC_)HBqB8ux>6GZad zQWn<2i!tWz@ItG(uWKvEBx+#vx|Z0riV%-vdKgIWQMByhq+uUjf7IxMzmgk;x0efB zduY|z#(Z`pffaK^#>rqE7hzTx$Z&62KZ~qNam@fWAt{DWDy8PSzbu0GX!G>sOf_TF zJ1S0_6pMij-18vkwzI6E>k8e;h|csbXq$DapLF8d!N{9VHQ)k$MXQ8IPV*wJkN21EAI$0$cTIJmX$-Myup%U&3d z2lojCuR8-*{;!qNL9|?8Y9pQBxDB9#*Zv7Eh)aBgXUM?hmE5)W^xdmJtE&@Y4?9k> zH2l}yuPGko!h?zisS|k@|8s3qHxq(3gw6zI}%GHg9NIR z!*VciC^w>>H1P6YLocNG;z}==-3;M>(?SL}-3~4r2tKVS-nO0}B<)D8Nfr-E)I_d@7m7(q%64mVe#O ztk{kBCA!Dzv*(^O`~K1_m1cRSkTc07P~*VNd>QoSpy@+Fb?(m3VUZ0J=~ZRjAw(0F z2PUEf1=DiDos6{BUEuB;o>KR5!g3GSu zngEnL;$BX0_WqR=l}D6|5QAD<*!SeqZ)v_&S}mfmsK9fJE;HuAR#SHp;S)Nr_*Ix4 zNag*4E5X*#dkMP&4ZvNfFCj-Qj^O;O1RZv(S$gk$>B)@1w|m_L_YKM3gJ6tTDo>;c z9ujPYtTu+f^Lzb7M%E5%+`vIir&7VDR(D4{UZ9m~L%V#8q z<;qO~U)v5{uCaXQ$h}YH${XcLfb5)dVbZvfuPK8OKTCed%r^r}X9*7DUc5H`Q#^ar zH$<{RW*4`Z!v57Tyl9S=-`q$z=VNC#^W@cG{HQfiy0_#b)%Rp{HG_#+;Ma+us#h;U z=cGZ#WGb`898pkz)-i}?jM^XzQNxq5AlaPuWuo#BSCTN21{78h4ZFoyPr_G~F>J%^ z6N^jV!-_cfWM0!R$*=&8Fs@4#_KsY?$Bs%w>Et~OZ=0D82g8EI!Od+BZ_q_4n1xB0 zEJDg3XR!EtB5q-@fx{`0kNe>B2`WWvdk$tUUt&^egwgI(I|tVd_>+TVSEPdKUwHz( zyr%F=T@p!2K3mCMRlK`sODVogVa zbZ>FI;4EPoyeOph5`~{ycIdR#@AKUlb3c`5d52gHgNO&@?)>ueFhYGrg8Pr>4+<*U zy7-Kx_XggP8~0n<@TPNqjiaMflGDjpeVsD7^E7#oN*`9ZSeX}LeeiQKMGb#R0tL?- zI`R8?dK`yPaV;9wot#{abE`j=rWJ8$#734~QCgZ6>1i~fpz9*phqNnQy>u_T_8k`& zFdl{l&NEjkKoiKDF?U0z86KJJ!SVzH@i`=BG4~pq%k4Z0jJvA#rsZH)h=bbH01X`a z0z6C14K}YHn%;d|x{>9Q0ybwUCnl3WVoPv+SDX`2(VP*9v>|OhUFe>nc{nD889@#2 z@f!GRVn@&vtL3^6x*6lJmRmrcH6leLM8tL#)q5O43bn0E^@EsALAap9XIrIm_Q2L!m?eiu<3eAn!Ha)6_26&d#970iHU@n#Gf%=^!zzt zuSAC#b5jd6&pqWdW{n>XiQ5%7Sd*X&C2XPf59%$Hy)v@(W%?tE+@r2q-98x#*A5Ky zA2SOM*ga(Rw(l6>F|;M4%=spG{6htQfUbC7!V!pb_t)~ycYm6?F-bh9 zyCtiQV=-94L2`&A-@7X%!p;Up=deXup}nR!2FE8ATp0ZFEp~LhK1_2L6LQG6A8<^Y zzQ9zaYA7pR()#*}WK!e$+6e+s)4bVA{p%4t>6-vejcF-4U{${;mTM)Q6@P=K1+$bx zC>mFw_ORgd0Im;!W|FijYE%k)BX1?r$4o)S=v*d%yZ4E)Z<=e$kxAMo!hR8ZN|vR# zK1s5r=I&)dgw)}a(LY8onMh5-}WK-Hn(2AGYX_yyC$#A%YFu$ z-gsXon(I=@4sSufR+747eZEU*aUKdE?lgGBj2OvMlKqRlj?zWDuxquv=`|0_Q$B#qJS{K9=C?`&Uw^cWP9E<|c5LR~nMi z!d&{ns4R1-N;zb4B(_cM$EQP6`Lt9ZdcBFQj9;UCpy0U;PYOQ=7m?lDJeaheP&nb! zjESA(Peee|jMhQ$TOnN_XTZh%q!KW$Np$b=PR8Npi8xIN@YWpB6K8%CIa#NmuJeQ? zhpKC@?M}G8HD)<0v~_Ap$vyP9sWDATOQUt92jW=Li9zMNNUk>iC^5rPLm=t*?azZ{ zU|OkVT++4+)(x>e6u_zxx*BXuzd}{A;{UUE*!t{wnLC##ba;x#4&nKbp%BesroN#R zZ*Gf`ikB}$;X+6i+9wcwVqqp@C7M>zo>o%$g)JuCV&cNW*U10Ef<7++VT5i; zx!fC{D1z$U?Vhlw_lKe^(dJVIapcG5Fbl{{vMK5n{GVA%u@2lz&0@>^@yP5 z!NOdcpr8=dGjg21BQL;2Bn7(XGg|Cc{uMt|>$x9eKU-LzoKL(o7~zqHwB(=^jw=#gt@#j@y8v4G#gtBKz4}5U z(Gwd&dDk;jKLklvHAi^{Z7XMwi)?zl#pk%hQUsQo+<|5&DHNoowASjMy}mF*HsZgm z#>z$lkS01>lI#Tc8EbXr$rm2)PtcpABzSk%79yGEaPD@d%BxUy=U|ghlOJLA%)jIW zpTcaa!n=K}79z(&ja$iTG;$v7pUsi#hqQO|d(yEz=WBJQ{OKlVRqB@bbEZ+-YG1=@?DyCiJ8z*$SMehvmjyS`sBI269x#o<6dGimrlax4maQdBDqmA@;g~=g_&S$) z4Viiw*Q!)j&mo z^%eJ1RFZ!i=cYkl95uIG9MG)NLS5$0=;hFiwuaMVv<`6l87zVBu#N8+T2C7~_pJCW z(F)!=^G72cAu<_<6f>rJX*x7uIM}~ItDyLc*agSgTcKVsvUT-y4nwT~YTF{#?&XVdL?Ry=l4K!L>SGnlV z=DV0Y4%3|Gv5~N5BkTsVy)j_{Dg3MpdbcPkvCdZ|!Ou?zxL-cvFFv*1-=a}sv4lD! zMPM{mB&O;s5A)bq<}6xsu5~QX8{LaTA$gtZF*Q6iste?p%b*x*YS& zAh?qrW~OkBBVRsV^AmjW$zt4e| zLA8D_(X#knC+yKDIg1JViMz?@qjb}Uu2oyA6y!GZ`My<<_nlw8bzk*1jVmX1Is!>N z38Uw}KF@zT6qQg)@>dHiw!uD5@*MYtt-Fq`V9aY^;6MCm~pxB}uH*;|Klb;z$y8bN6TUIQXET ze~z3QH3~BLC+c+dZdcEz<*|YhS1*$CuSXF52K~FI@2;J8Cc!^AsSCqb1)n#t&!BfPU_KqSI87%sG6IQt&Cho26Jpa+l@D z=;&-Ez|KYTu)kLMME={RfXN$N;+W3H?56*B8nLwEIB{e1EN6iVP-AZ!&iuDI?&LiM zp)~z0R^}e+7mitA9{2Gy`d4i^0yZpW)S6_H43d)wy!6G52ts%^WVKs?gIYn4?C+^Z z3Ql0<>Wdvze|GpKFkgoUZ^`d^XyT)yv7h3# zlOO`~hDq z6%f&0m*>h5DJBJLz6Z5Zbw*=GujgZrAA}RjEf*Na)i0}6OzHxzItqf z+Je!oq9#^^g?c5UHcMLLzdv596!3c-Jm?t0?Q6)X2iBeDR=P7KzojH~$H0g`JvC~j z%B42yN~su9%yh|1P}ZY#gT&TBC#zxcVE6~?OEe6Tt@{sD4Z5q zs(&Ngz)^N02dE-yl!4EP*4~c1zx8ulbZtXQvsKs&w>NJM_c}!)y_%XW#*`FGMM@Q8 zMVqs9q{72P+@0?@eDs|t&v>XjBGEd<6h}Vo0Gm-|cU(VPh%5wAmA3Qh_)hB~kk+H+ z|9EUOKiM_VC@eO5EwlHxu`kv0EKjo&q~wC!8BuY~lm@hH_K~;cjieimfDWIwdj#Pb zqv8#6kKjQxxLOY-XS(yQ)g-9aGdM?-VfC`u?rZjH`)HybM zXXP`gZF0tus~- zZr`h(`UN9J6%|N>tS4VRLD{?p`7Me_qr>g3Yt<`|>!sU$43|8%V)d-$7`r@4`#~yQ zxeySRJs4JmV32g?ZZgOu!57XiG9*6R@DMRhdmGh_c-4X8O(XADzraY96u-r<=Qid^ zK2_4{>;5iUHGPB249R`_n^5$7mLCCVwGUYm{)!iOD`d6N#JwJD+ZbD^+6X2?7Jf}7 z+RRYsO%tVQqJ)Of48-z0bf;-mC4UqRVHXkZq2-?`W;OQ zL3)(o)7+G2;5peJVQ^SkM#)ReEC1#EML@ga<4{dq7lg>D1^fXV2rJ^v$-4iumMU_OLIu-+qOQOH9LTb|gSmR7x%~~aI`vHSi(hjM(3@X0fJ9zI)fI&QyrMovfrGokH z*>SLy=(1@SqjX=p$RLhgocq-pAtY{0uE_|okl~1DFEvd0yAV!Uql$JUN;%pnJ*>t% z0(aVpB)C<@r|G2Hq1^vNR`Gr;{iKF_T|JL-ROsYLk}6^N*R zh2(*kBnBc5f$Q`xDLU|b`Kt+}uEi^ZvLd_MEmekvx;`E z7Vg;U$!2LXkKuf+&d$bRNNcMbr-Z}3PL?yo7H~h=C;>RSaT@Nl%RT>7WnY6{l99XcDDVv1fA@rV}F6F$gVj-5S{E%)6l~=UEdj;a{K z>;Z_GPGbahkhn}%k-!T33w7_r%Cd6StL(Mz{~{8cJ{Wo-Vr7Nz<_tN9r$9_<)pmGvzA4Ry`=x-d{r4bobV-A&_=HpABv0bPZ5 zZH2amD+<5QF$eqt@r7jiokYKVgGqYtfYHl#^^i%13#h}@yJ?nlJn01_SgHpOLO4kV zlOyueI!B2eU35~6UD5cs5->?Y*N`<#O{RbLhBs}ER!#Rfnr29V6NT~ZVEwszEEC2S zK=b)_b1A0QO1IO(K8Oeskw>|KhH!E9C%YF7t*|tq-J)MX4B-`|pr#;b>IAV5y8@MX z*`vwFu`?SJc2b|Lu{gq6ODd*u$pfXHAFOyewWVa8f&W|_tNsDpTGrn3iHAB)?Wmq1 z+Ftnp5@vuoD1?k{EjfCu!StC20zNtM0Y2O??wOQKeD$#!{9rh_)*OuilQW^C^Xq#R8&Yxd_Z`|a9DyY`vMbP58%)4(7AlK?9zI-r+O+^YEYNl&=A z6^g3vAOPpnstP9zPK4?V)m2T*p18Lwbj@&f__iy7x+KN}1Po~97t#K!MY+Ipw+l1; zhvrpbNeYCJfocVl{@Q2VVD`M#`zGQ}gVE;89DM#)FamyJJ2MpCqp8gAVwisEEK=sQ z_C%ztSmctU&ux|Y&T|RmKNhs!!DJpzy~?eM^ea&(tVnH}ZKXq>CKR}e?rRTbp1gJkHkICQcUigEX$k!UY`qO^U>vB1oC!)}!aktl^eNZ#`-u z5EDpkP{g#F#Vq4tj5hDB!KL>RG6;UirNwdAmjFfmaOo}SaMKZ8w{C6r`v4UJx{K&$ zEDtDZR{T*B27w=HHL_y^54C^>qUYEmLh8==_m2w<=NI4T zCtCZzJBkD6HT~bm9}6e3=W~5>%_YG7u|YCS+@&`F8RW0pc{c>sF-I8JA_FDm3y(s7 zFq|g?e_SB}Y-DqUCOtwS9eAp#p1{AYLV@#I{s$0%SDnZr7L_`HfQQ4@t1tjgAeI8MA?S;~R^Fl2hy! zk+I1xzc@=Us4c@jNyqN5`q2o0b;WmOx<+p$4VaO{UdL_3^o7071@BLp3XIZbqPS#& z;sOFf{t?XX{Qu~IlNAtJ?kj7B7a%yA!ZSPh5L1+!;PeSEWyF=yGaOm2luv01%1%-L zZi?Cc;ZhJqYan**MocDRZ66C`S^_-9HTk&Ud=5Ry1Wa{==?&YF=iJDwI&ka(HAB%4 z2yfl5@$*!yAX7qJ7N=R{oAfY&N5PFgtJN;+gk`K=WP^}n4o`mndMvfT``Q15h45d4 zQam?O3RBm8oB;~XEAVbQSVsge9DU%e94hJj3eVZz)OD^3R@A%J!3$E+*<`g>pm-XE zcN*&TWsaF!bkD`dMy+hE-BwKE>C0C0_wl- z&oAv0LQ_UI!V<49H(X=Y1O*%I1>u+GB@sCuoEN3Kt&ZdZ8W6fxMb78CM*E$d;66YrfB{lXApx_1U84dTD(HZ!(;_Oy`ypyuD&S{*1Q zSB?teJj#t95+@35oUV71;A`~PHpY?RNzN-RwYZ4V`e+XBc9io5F}+@V$OKQg#kPYl&Rg1^5qGyM}&t*dt~)tr`q4p71u zXhmm~ck|4t)SBaiif=HXjpg&4tHw>@2X!g+Nk^#l(mXH|>T>9g`%c+rxzxJGak71;!4f0@M z%4Tzra#@FdVe>fFL$?e$zJRO-dl&SU=I!K@RCRi&f5q9swZ&HV`F)z`@qZK zT=n$9O>6pqVcSKaFQ0WUjW=LR`TZFiK={(ryKJ_6U!Z$;yIo<7e{XF+`B$9dvC_>X z+tt^Ai%ipDL#h%#yGN64$tnJZylG^;8)mWL+nScC{Goe|muyPcLX~}hN}BZP4Y0DF zCP?eMYW|2k%jAjAm`p(-H=S%Z&Y~tWPmUV2zm}0g*_lJlOFwk_Lz9$YZ+Rv41@$_Y`0S9hV;8Y8F(u^ZNe%N_TmS43m+nvX;M(! zYC+(~v5xpE>T~n=0Ri)$XfE0eV9i;bOWs2mKp>MnNozT-DB z-rprb7nR*moKSs$D~1gG-x~EcBd&$7`G(jPFxH*Ql$^C0gIdl3!ioSv=Fr7r(yt{= zy6Sg}njcpUhh)(UnQ%JD*#RYJXcXdwy$TIb&_ww&K|!K0_D1<*`#3O^*45#Z90qUU ziN6|TMchxazYIew9LVkW%b+Z?W;6|>pK6U7=Vdg}1)g!jdgDKOXr3AkI+1kNK;&$lD^HfBer7|wuMqb&|MeO9|CNQ+TImW>L2|M zs^Nhss-|79zwb?ao@bvX%!(L01lsr2JZdF$t1V0Cpz2d_2uTZy#vTT8F5-p4w9-EN#RJd>rm|J zmX@n$VbGi+4^z6#iKrSn^$bJ~gJE|y;waJeAzybyokD6x>K^3!+laanzAmdD(LQ!R zO)7%^4;0YRtgND1d|+=dyypAxI%a0Vz5|Z2FrqoV`os9vA7waH455jdsVN;+0-klL zf&MlYz~0vA6>k2Guro1VxA~?GYlOt6zrl>oVOqD9Z=&iNwmWYkVaCgAAF-Dr)r6Lw z)WZsUW>;eO!bK<0$lhnI<(NK4VXU#4goFUOAabEDWci%EFH#9PAZgyPhI+%|L{P#T z1BhKo;8S-cS%~{zhqy?=Ao%2FzdTK|4WZ|XDeK$_!2;}$k^wE2sq+3rcHvh;N&*9^ zn^g^a($Uog7w3-ADjt{jddC~Yq4cur-rdT=p({raHHca93&XCKp6T+SQCASv_xDH7 zI+(eWEA@Uhur~g1=xIQsm%X|^7lpFgz_ZaG1`jwm@KG}H$!&m#30V{6G_|lx$%a>3z&^XeG znU{pLC&^+h9)GFLBF`NXaQqoBRJzpxc7iUi_BOnlH=y255P_0eaO-6C61zv!*i*w( z;^&IYs{H~trg`PSfOkvT2C;rt7YfdI@${>?6s2k$eq(v(h+;vUJ&#@OF!}K?gN{tE z%PpRpC9%mB5lIW8>O?TQ8`65VMUIV+4DWgzsDO^9L=;cq`vMg1_<3i`-1 zf`H&vY6~`|Y_4uNO*vJ}y}mp^qTw>r&fb@m$cH8bRfTrg$4!+auXXmpJGk$CjypQy zf(jlzsW``dAy0;Elb8U161sQL^zNl%Xf9PzAdRd|wf$C-)&8C+ETL$Z@{00rVMnLA zQ9Hi)OfYmACS0EXFR~FE;3P%u!&~h0fpK`&hm~&Cb*E#LTLgGT^yZefQU%K<$(E8n1HY?J4>Fz|*Ozu0CAMQnk6XZ)lI>H4ZW**U#FfQr=)|2xrGKpkF(K7TT$ z%CuiSj1Me;7xtg3QA`r%-Ij(_VqpS8V&W)w+gI8Iq{a9x ze_SwL1ELDPO%s-1s0OxA?R!Lf>@I6+<`|(wl0xLd260icr0pZ#GJ-%EQz>naw}k8o0i^M*@>)Eo zZt+z6T-VvWxHR$C;GpHhV(jdL$+R?}87$+FYc_7s)sdAA!*$QT1Q%V%xbMvovp`?e zz}?)OyDlQ@T_Y$9>9+18L&g$7;HlK5L57k&*B0}*?~CpZh_@sVL(N55JPP53ru>p&AKZj+bGbTQ!BLvc zckV>JPSn4t%GHp972_0=zySGBlMWsMxkS+q=>0BnVEEW1%P*(A#t-9wc8uS`5oAR@ zsgSb6jyJqA;a9_GCSq(t!v(2|B)X&+LbB|8N@aMrAmkEJG7Jv836mf?mrMDpr-|%q zjTG3gepN92_UO45ulXBpnAYH$SB&F2nAk-VWyQJV?_F~6snt`Tyn?NMpi>R)Xl~}U zi>le=M2WH!*DI`Xr>o#R2o8Qft(VuU6;Hj5uR+8>R;B9AXwcL&umW;i5w&j|KSYg} z7{qsB$-e?C`~LE;%-nptr=;s4KBYr~)0cU$eWV3ctU{_Of0=v7CYiPaA{UP#Er9ge z?JnU)5+E=akYrWKWXy4_U2l{=^;|kUY2yEU=9CuY-2+3h$S;8mYwQ%5f+hrMYn>(V zRAA2jz%BuGGrDG*k>(^MtvJWXK?h%L{&mIq0})uqkb&&A`U(@FK2@pt+s%sJP=<7y zs!#{FEhir4G`>yhoQ}ivqk2~PFan(6yG!}I_1v%8O|6@l4B6h4$CHYJi=vlbSA70@ zHhgs8Vw49L}!NF+=rkQ`f*&(Q_9-g0n$5f z*Jyo}y9g|k5O}e-C^pN8eNw7+T&2ZazHT< zu&LusWjlU>fh~H zvcss`7`n;a7&~Z0$q(oHhxOqsk6gbE3~>D#jS^Lcot)C(9Q@N@u$wWG&Z0fZZu^+Y z5=I^>%y20qs4};;n`DifpFz@a)D*quRx#Fp_Evf8lSe|54v8o&5p?W81-SIV3XJe$ z-77-e_s(%RLygIBg+-?sxVihE$t2UR!IS|MBGnv%Wqn)yJ$u2>W zTi&YJ{5I|CUPJ%9Wce-&u^tyYm(VC+Paabw+-TkW$Bd!q+h}QB3@<;YE!W9?Qf9il z6<5F#Q8pbC@n?S0?q{ach-X|)23a!>p&PMG0&0yq$j<;$I==%n6w?;41bb>4uiBiH zTezvG!=b$&4rG}T{_&|~o~vp{44XB3SF$;OTJkB-WNDg{U9x)P{=Py65il4lT$Kl@ zJb_^nKbYRq@!IDkUm#NUjU0UDugx3K^{DNcF{PxFJ_NucB?T zz=5fdVJg;XI1U$CBP!a}D%igYWF)<9CSjk17&xGbvfX%r`x|qRRV7DnD#2`3kw=r6 z3%SzGJNl@(At=_(Ax&4j1DsMp(r5#bdzB}UC$f*oMe~Zs>DDGR9e%9>A9tL0R?(^{ zKGD4oM9zNm3~pIStTzc_Ry}&(>OD-ajf31YhdM(KUwtNOclJj}G=XV`65j;ZKQnrd=O z)pGQJUgo_v++7b>0!9p~)dPj9q^nL{gtlq@WXRLYx3&Ozrnnh{aI*O3xRG3@t$SOR znz<*B8L4F8kds1|Zf`S+uaJg%il5mkzH+ zZ))eRI%ZMNRDMD$S84nS_=$AL*ro~4yag_z`M^)5b%aRvSCZ%Ww?{(YY78PlCf!@5 z%hnlfdpZjxLM*0I!`|3Z?Mf9n2+Nz)LfC==rlFM7u)@JWo6*J*Z)i6*onPWX8WciTzM8nBw38*T)RtA>S^t6y7&ua*m}$pX*Q8IK zPY4$vh|DJe`_z8xQIcFp^husOEa|)p*Ag8FmX}AMAFrhA*75E&f={UsYzO_6A9SeytF|>U z?zfdKNGlQK0ohUpjc?2*JBDQBQ?X*fEl{mSGt=(Lg^J{{X|p=vIqc!5=kr#uQhYIL z6h_^VVYz|Sq?leyCTz#){%rl+sQnELZ7Y!_yTG1KG_gO}0XABMB0tLOrUJ90z7MEZ z2p07!>G)H@y$>>XPpcg^zT#%5xciNAX*0)iHkW7TNi}1-1TPbAKWbS~#jtQkf?~Q6 zr7)Mx=I#S^>o48)DP7iij49}s=mKCl(|R)eL~ir)(voxmzN>>PFg0=b{;R~mq;epl zHaZKwip_D~1x$Lz(JiWhn*jOKK+R<8=;L5e5?Uo>f>hd40!9ABSb(XlIUnp#ycSt$ z6>q2Mx(uA>?RekR9u^?*Fwr$(CZQHhObCuC`yU%&f-F>@% zKt|3l8JQ6?#&|b6u4M4A+$Rjy!m3S>@f=CwKxdH>zO@DtH^cqxUT5f|jr?>QH<2&)ep0Z0#rka0duePh#Tod3H%L#uCM_~=C3jS&6B9^rZJzM}6~;hI z@D1;`4@PEV9OCKp?8Q#nSSWr&lx>|1>^n!)HE5acE3pm(rXVq|x*_Qj(CrKvrLzo` z5g|Bw33hETJyV316mM4iEE1t6W@*QHHtz17kID*E31Ow=(Mac*umqIWz#&3{YY3kd zh_{kK6fXS_oo(CJbMMM)pe78TU5pCHj>6i&6JD#2b`yCXDmmi+ni#tb@QvJdH*X8$ z_^97iNwknb3RHhw$-Z^vVey*7@`9Vaol`**ePpvAAZ|T1Po$StEmj&aChVopfVf1v zSG=a>%d|Gk^2%L7^2r-j4fq`#0@)E0_rOVMk)0?)F2yVN^1zjG4QPH|2a(=@nZIaF z3t@G#r_GX%T4X0LdP>?Y327ALlEB*N8X&}xqLcl`^-uCKBnNwhSN*y+y4|C{ z&qgJK?!YQNC*wuSx-}O-lvznb{MVd<= zFafcszL6Vm`+k@cyVJDQ1glDtPN?Ec8^H2Y=9g>a8qUG9)g~+CVXR-j07LX>~_mY#sE=Sm{Zhjc`2YC*Z_|0*C>!HbRmGy?ExDG(45jEW5A~ixXrk zI2+I~Ro&kmA^pUXZ@Hz5>qxHYT3qn^U^U=3JB77p2YYB7 zTx-Dw<^h;sZ50Hz{R(}ibs_nysrV-xgcH9!l+u&Cmf2+|lkF{(3t$>(%MZDRVb zpBuw*xnMW9>;%#X+L%RMR{6jS~SS zys~EH$<1-cLxDWogB5(tBsK&eL0E@@s3XfMzeQ;2cDC}Seb4&;_1cjH%;Em8rvv*| zIOc{U`qbAYhaLUc@g!L}vJUj+SFR%Nm(JS=d}&h9_y)w)c2^2@GkF@OF66;Knl1rH zqY6Sf0zh%kP`}@3^nf|M|0DEaUVmN<)-pKeIC1X^0^sP*x{d+hW;e+s0~3&7=Cu~o zfpq&N!yXA_5dG&(4_J2a?gPN}g}`p~ToK5dP(1q7h?Xv?2uhyzd1^;3Z=-y^R!hw*_j)(Y zJdrgW@GM<77{$#0_@M>v_{wTK8od6#ihEgRV!En^|BF2ZtHeB?*XZuWrhP0IvIZ+sd@NhM#o_WX5dA|}=~+TT>}A^~W>c3mOt zQ>I%ceykb3K~$C#YbWgoVTFl-J(f$LZj|XOtmLK_-b2$nROY5-;;-HDw>jE{7La;* zxxp1&dgfnIe1KLMg87V1Ra0E46!08~2`N(23{{d>tp1-phE4TH9w2}Brdwx8A%ivQVD{45 zHi7zgkz;8&3j^U@y@kY;vypOa&SG~dTkfFv`&EyFx{bKP0coei67v8nv&QGKwR!_N8%55@wFN-m z-+_>O>x0H@u)HkyGn`8zHfn+S4n|G0Ed?on|s3_W7E_hS9goS{U=9fN(f zI;FSxJ_q~6g+d9KG1Lu>UZW>T2utm~e3}vMjiR1c=3r}r+uU9V9)TUVK3C_r_hA?8 zORlJ#MeVZe)JtPOY=xz4-l-hnaK16T%32O5#UdjG!|`dblTJG7RDd(BUQn&jEo7W# zl=<^lv?TF8a4rH!h$H=Q;zKe#>{Q6WZ=bs7Dc?aK%j&tH)`1e`Gfit&z;=_(;F~G*W5r*3nS?oC zKt!%chClJMnfv(EOc&LVNI@>MIB1*+LbO5A0%Cz444@u~}?F4ZuI>s{Thm;oE;bRAJb+OaZS_Cmx zekb8DYycfLEmDd$Ry#>J^J>1Lb${0h?HOhVB{GUAxa}yul+Sx?^PR<`fiNsj(-ZO~)27k*sFJI#NEZ0w=6sDPsm*eQdfiHP0y-J6eAD>8@*KsZCCjC$9+p zjxWQMoQN&9g!VqXRlld}DO*NPfZN|=;BtEk5a_yX!D6tgN~G6!C5lQZ)aB9#-?uQ z9E}H|hHovW$U80T<&scu+r2;~GxK`En!~h6G)`e)9v(}o;5DJMw?OarfE#qn&i zJian>@0QW~EFP@`_R#}R+}H5}u@MS=4!L_Pg8pKsV?o*lm(_ZSdh z%<~V=SutBq4#Uwmz8d7*-B3AR!Wd4u96V^dm=AO)?yFCm>&kYJeVl|ll2J@WODH>> zc8F3bz2O92%FVp>u>Wg@uic!FzP?X~*XYvwH;2zFPRr9K{VJG2S}UwVcz;VrvnlxvpV7Q&Oc!uongLo;^a&?Pv;DQu6z@-J6Hl6KvV?%UY} z2sa7lz^*?sG{s58%D2EUY!2usw?g_?2(dmAEmdYPrAFXGeEl}q?&Pv=~@qD3Nwy{;t;x7uHt&*E($ zU-j+RcfmE3{6V-62ZsVUvTLm)jUS-o{(irc6Z)nUYgQu>Al;Vi#g}%jw@f(VW7e26 zT3&aa(6tx`aSeIc^D!j5%lE}wje?b)w&KvuIYk*P0UykD9AyI0cV`Hf0LW&Q`1Iox z+k#mseT2bk=6!9Wzh3^lo>pETNk>YSBxfJ=B#WmO01#>Eg&H_$c0~;aeND%~Vc@VB zilyW1i`W1GRNPj6VHEd{c#e>{v<jV zhJy!L!!#U|VEN!nmZ)jogc~g%&2!uFMgnT_bBD02be=6TddlOmbodF!6wV)|Iw_~CSCg;K)m6gw^ZNY2z?ex-u-MeSSGIG0^1 zceFf6cUmlP8*Em*44ERj@VuDhy)()`aVx2MEeecNi~~+vl-gwDOQWqg%TDuXkCThK zst~51mV?CpV)T3pk;`T6iktTe{_Igj#d9ju6uD|eHtWQ`d`FZ4sE=V}NWIBVZ`|js zlMK^hb33Ph-`%xA2e(gWI{;hbS(F?EFk~gJiKNCyvLzun&kq&L@$TNwAC_qE9g{h& z9b%P%xJWtHGiXjWvP%`}0jGdsPRFcI@6Ur6sY!D4L#3y$uIBf|0swJzo|Hdj&;qdN zW_I4S89o+yc2gCH{F5pT(9ZC%DyMhx4|ildd=jC!bC0C3a91OIdKIn-l}E+!HTj#j zp%5i+;A`>{u`%9f&^$cd1pG?#x6y%&10Cv zrn;3tB5&Qgk3adL)rE2b z3JUD;oSU5VcfrXq=W7we-;Qg?Zr=d+lzqUk(tJ4)NBkFDV@nEG%^7v=~rLF&ed3Vdk*eT4YIEa2O?feefA-z0_!qSJ-Y66PuS^e z@=)`7YUULD@qPEF#~M-9=6rxhvJOM;llA-U&sk^N7?@}u;CqOp9|)DbbeC()b0-_w z6aR$SoYC<^hvCTQvZjf8@{r(;!@lemJf|;0$^11v^uSV7h0`l4r5+IBu=!^4U zLejkg|Az2VSLN_Cc!yMd@IOm&s6#vzJY3gZY<%vvyihdbKVmP9BYKu2wd>Q(UsZSo z8Mx8YyOv*(6}SMP>TtXFAN{@yn@si7plBE%9f)t{@Az=A65$ojs~3+qwX^2x#yMR8 z&jY@BFRQYBJ2ajtBn6&aJ9*80sPWp4wlM4nn^NxID(V$LJ^@~=yv*e!VORmCIZ_I) zXj~Xy;JLmzi0i*f+tu0<1r*HA0sne|OW8LChItqR=t)wHXZlu_T;lR9Z$hWJdOp6h zaQp_52>%;DOiE`&lI&C#dQ$Iuy(WCCLk;b$pq0Gni>yCx(+**$e@Eul)J&#IOvG(z zF=^Rnf{N$}2dH}%$s-hoEJELGMUw4uY-ocT4&Rd#?V;*>PJH+OSzcM7@PI{DkVo?B zC|LV?DBM*;*{UE&G*oEVkT97_IVeRZJGIwwrF}=I^Ldl)P*zu#IcGEn+<*v zAqTfu>yTB>NHSi=Qrk-6%+_*8hv+sIHMboi^E+RMc46#Q))MXbPfme9>8a2?EVK{D zKzRX5kDLc@&WVlp-i@(%_169i7I3G*73VQZpd?c41bqWq$#)W=Oq3*?ZG4ywYAdIQDyxiLs5$_+ueF^+}E5&z4gQv8^KG68e zT=Bq+7`8RN`ni331k*~C@{HUW>t0a|_D9G3nmBeGY1ejG^6u#7DR8*y7};2hpwA`U zZd|Rh{mr{jYg&<#+C;-Uw?9jnDp9~#qApb0wbP_`zjgVHcx{JQ;FP1W5{`=2RvkAu zj~wVWA3u?Xt5NgvxwD#C2P!k9gv9L4t*l49lS*rKX-s2)@qS{g3WURKgPUnVX>u}s zq%lMkjwX^<#pMgKvYE+f96%iW=@6s=$rM9Lua(5`dWVEp<=nkga!ods47sB27Po&AU>U`U#Rc2~N-1M+N+_G?J0!_SL)sXY^O;80e~k*jsD$ zCR(-~UF()u0{>PxI?&~FY)HEZ%W-VCr=wNp6AuXM#SqGcF_EEdyZelj4^YsKk^F1q zBe}7^IXyq*)tTY?N<*}Y9aIxSD^(`HR3Do^I73#tgZEH zEYWZ3NS!`S`tIedEwjN~H(G%BQ5zZ!Z5$n71fZZ6{{%vwL-f2!V@ABxi(_B{L>sGW zZo*^Lo@P6`w)e^>(7^-Uh$OWgDZYni3rH8NLDN26V5W)XV&G)noGvfc$PvfZA207D zI+-!d7xtqg8%-T!hq~6f-gg`z{KsZ2vDdO|k44|%+_Z`+KxJYuxDDAcwSwZAkC93T zd|}+hvF9qHbhW=}^~1x>fH5J76hj3Rbmp2Nud>id!^eFs7zQu2PH8W3=Q~YtB`$Q& zd;F*%xb9OrSG41!OJb8me{vHd05~-_#&yrnV{6Bk#eqxyVw+;-!d+A95HtU&h=&k5 z{I@q2Cy*oXA00i$x*&MfJJ@g2ZNF-%9tNy zSw|yKut|NfZ1JyB!%*!J^FrI$KEv&j!e6pVhm!1ps@0Z=t7wG~X zbZ2lZRO9heh+hwY25np(6(T<_3j~x772In3yC4rR$KZb&d@OL9D1#pADIg6a?YThj zLCMDh)<^VmD1(~-?0~~dIUfbuWA{`41j#@;Oxwh8?CXBHo-P0mIS*R+L>zYx^Gg3 zRa`7xV%f0^q_D~UU4+k>73@l+M-#9)cMj(LrsiTIA!B3ezP_{ZRKUMlpRd|t_$(2* za!ojS&fxL3q8RH&FOhd|qtbnAII-A9c-u+JE@i!t6Wgk>RTh#Qro2I3r@;+?BVST| z8v42ZJB|1SC_SOa<;#}D6!2&5WHQi(NwsB?zNZk0el_Odb|1KbrKu{fVUMQ?Vyk?_ zWbKmNO?2g=sF~W&fb^~9&<1{=FqiD5Qu7xfY32I2dpL6FXH2yF_T;jT19w|f&!xjS zlISu&LE1*hoU}Hh8DeaU%yG}8lu8cRp83~LfsHccm6=wWYm?jPOOH$s_J4H}_9*ZXz8K760K+HHrPV z`aw$%?=TdEac5wnl-h*n4n#r=MhyJ?uxR-%*&Y#9m^v0ii=cF=M>AF+!qyE~2!9!g zlOoUo8`%hhR;Yt-&Q^;Oe>l#EwkIp8h3>Z}l^4 z4mBcS2n5kUq3Vknuc|h>HS?@Q@r?3=tFwlCk1aDi4CMy_Dg`7E{oAC*Ib4 zyE3vg)&>wFi~NZ63iJN!1+<)P(=sub6&rSl!Qidkqz1?2sohE0$t5q?R4yeug~27U z{I!Dd{_{h(^E*C#$a>TbukocG7+$AP^Asl>)0wJbm$lMvC~^X0Gdz9 zq@THi-U7#3TZejTwMXUO1&iZA`!6Bq8}~-961OGbREk`}4n5dDd-`Ig_C=8Dd0~H#8vrq2PRakI zg#WGQKiC`H2LKS6vjt@E`=QXr%9KaZszoB7=@btcHMEvr8to@~{f{87zbQyz5c zn;8^qB@M8_li)H_Cs0gnKJ-vJ*+5U_eTWBaoKZd5MSth&Q6OKI)%vVsjR@ZLkRoaP-tOZZ@1$XZ0PzYuzjj%nKh7XNQjRm&@U%U z@!Q_8`0Oma>FtrKX6NJB5gx#d$F-;i;%^eX;0lZ9{*7k>NpJN5|vvctT(&ERR2(BMFm!KA+Rt0L%&u1{j}gLt4c)JwSR zilrm#Sf)AIL<)!k+%V)2t)?8g2-__%1nO4Gwu>Zf9&N>9xVn&Z-x-zLuk3K^lK@=JD{!N$!;Ejm(lX{QFpdp ziTX|7#12YF9>t1E*{ zx`c)Spbl22P7Z`Sz^VNz-1m=~M~BSF9T!n$ot(%$>Ioae2xA;=S3wHHYN1scHx*VB z=In6vhc-A1k&jnvRljKJcSrH5fV%O-JAPhRenO15Bo z*pkI)rFj&h1Jxie&4o7fI_?RpzVKQX++S&_NJ(3tIyt#TC5%~oDGo^|lVTv#C0@Im zNDnm^JoV9*2u^9%nt~$f_AOB@+7{@ouPPs485%w&1}hJJ6;l(PvTe8TLi$3mEr9a% zAHd<-PqS87aBwaz^pI$ ztzq$7jueYq?S(U-x_ItX79ndQ2l^mbLjP5hFy~fJ%A6Trodg%ZPlafP+dtz zb|*`gZiw0Wkf|A|kHiq~LS@bIYpBIH$r7)+t$eVcc&`82CL=oDGRZHR6%dn2Y0&?`WW_@#|h-ia%y4aN|m3a74>G6pd{hh6J0u3Ti z^gh8*D73={W8D-wA5LxNR2c)(Q!Qcf_OBQbqptj{0F(tGhj4%mfk9`K< z@;Azg!%Llvw~uvGWO#5UQTL2Q0$8q@WT+z%UTed%JF) z6n(C_ode_E<1{BXi@~X4YtT=#!lXJRyun>2(q942vl3S+cRYSsS5$Xxu^!JoS87RS zWX^U>0qMa)Q^gz_8L`knF7D8ey;cgz3dwcRy539B@)HE?JST|1r4Z`x&y%Angp|I# zSD|n=lE#l9wiD_xtY7He>fvgT*@*+g6#YH$$objDpO4SUU}lha7npF+nL-^f&cGzN zE>>1Wo0F~17c9;A|lK*|OK)t+|D z4Od{nuNu1C*LD8%KEQXg>~k1@Mp`IZp?K@`4gpv$O7mUVq=!RXuh4tgwLXYB2d49( z5YytN$@H|XIkJedGxo@+!mgm9Vc4tRW_ZG)vKDGb0NnGntX%R~0dta<_eu*)*1x5F z=~BafQm2K~Rhr@}Ox?T(#VfKbM?rv)C0|}_Ge`RV9oB;(0B?=ar4!qC5XHu*%{GWC z($>=(ax=@(Z=j#H^hjl_WwL<+PC$i6aqOk5IAoY0H%&(Wu(f?{+Y}f<0I6n^RO_%Q z6r@TR-D<;(lsAfNT$7Q!TngDeI990&$e!Yb9Gyy+NLG{mm5g)DaI=dB zw}$iy$YUH5Do7G9kVn?kMd5D%11D{xH`;J#5%f5!-D%x?a<0u_nTy>MiWFPKSn{va z(~?7|*^18^0qUlotB+}Q8>J(&8GwXVfA%?uHMQAye$h#Lg1zuI_V}UeUp{Xjk5!$%-9KCv`W=En;8! z^VP~gZn&$;O`A&rDZNJ4;cByT>FnA#AwHj<#|M!C(BtqvMSXNfL_<(beR(km5DATb zg9UamC&vWz_x+||s8bkg*rjA!dDF-0D-Gq~wt#*X zt0dy%U2-p=VP`i_?JMu~+~moVglZJAf4AC!zRvMY*J0;Sb`Ng7_S8_{0?VS11sR$H z8kdE!mSW#BhB0>js$&)xcii8|)j6@qU-jzN7X>_fYJwvbcHIhyQIR+$f!Ii^dZH%Z zBY0V+@a_MYChJCQ_8+3@*mT>U-(IXAcG%E1-ywP;gnD86v4;`|QfG7ruJ+}m)5w8K ztvP_bpV6>6mdZAu%za<+R0frRw5M&tjbQZ?o;?tqB=(ADb%ndHfol7?m^&dZV!GfU_e4ymS!fML_q5IpEX-@hOf_h%p5l z!r-y1p+wGT{#azfq0eZH+|bQj)U2ZG25ftB9bM6-__DmY?7q2v@ivB_A!#$Heu%NI zul<{+Q@6y6EHo%_>&_)~)_S)DN73y%VMor(Mx z9JLHv*S%~H$!yHvUrtO@Oply#<+jS5jG}mypEvF>b3CiVOPpnRm96&@-S2KlCyC(5ZP}Ssukv3{RJ#Gnej zl9@9BA7g5S^%7ezjXXcWKgE-c4qR_t0ZPqDXn}tr(UV@NnPe)GU&-FMV!{I=IVMM` zeq1L-kR3DH&$NYLLh1*VloH4J{ui%!)9)Uzzxs54Gl!X_$1GaSBpPRWAyW_OoZf& zHYG}R@2C|?IdpW-rNGbHAmrCiJ1Y{$n1uhNQN=ok!~z1OkS3hYS;Z#1GBeB*6sW6MQu}QsyrHj$VBog$FXSpd1Vv_*IQ`hsA zRO78#&&hgMi3h?^99PEmSNF&sOd`{*X`G7_ISVNs(DT166SXsr1VjS2YUr2URa_S5 zE{guZb)Go(qx2IhYVLX%|O*@dgejV1^gNWf%=fS=0vs6P5q7XUZq zV;C{$?u+N;wPd2FMU2eFC{T^g+Rf-#D&E;8DgYY7T$Hsi;TlC7C1aO# zk9ccjv4A*-&+D5x6kNNXAtA?xal6BuaNIYvpMfFwTh`bJL+{+Z01un@yCVx=&e?xYaciU9s)Pe`9Zr)Y zJ>VYArN}P7nTVS$$(Rx*kNk}zjs^JW{T-6#L4kSuT_^#VbMZeF7|SqGV7w*ma!Z<# zZ)F!&G0MYbp4R+NNo4u7+>FE^etMl_%*keMM=quDKZVkoDVVizfNPm&v4?z&WB>q= zIDw4Y|18tq2Eg$NH1Et6oGA_=vXcQwb;4^EPOEF*9;%=q?oQv&y+{L@P%x4sS4DG` zu8VGvhmrAi&luygq%flh;jHruYF0x#&}{cK0};o&PUWZIiM#>nv@jTD(j1GoBd_ml z9V*;@ddu&&7@=N|H667s0HgnD-yx`)$vsa-&)P8q9KB=~$$JFQ)~@KeyyVRuB=0_b z@~b|C83-G9uW27MgcpH9}ih8Xqi*V&%AtCFgna*7qF;Zh3q@BQPPbuW|vBx|2=qRp3f|2ZWn z*zFS}Z`eMhVYo<5L2?AN@7NSNpB(Y*ecVhghjX}Bk;9Dj9Tf69v~)QpkcFK|>3(P? zdwQK{Cfmn-!yd5fBOfVlWC7b6CuQqP;Mb=jMS9S_q-Zvv3>6%h2aTht4Y1@qjDGD4 zr;B7L3);GQSgksVZ5UQ0!T>`N)mucv!W$>82`@6>n(o&3w}lVvc}XdbPwRSNINY$o)Q z#vcQ-+|js_MYz4C?PdEH5m9>ROFp&SGzNVf>@BWH%=Qr>5%AV>C3^1aAA%%A`UQ+m z@D;J=77~t|q~VMQD)eQX7HiwY8sY>%zt(W2hGoA<7@D3HrWOwv&gxCr8L8*3A-uAZ z2vjp|**xyNHTL#a*oyxv)?==Opl_j*Pf~&9F>Xa?OylYgtENog&wveGqD=DJqaSSo z%Bky*t*!qb8!co*qIj1{`=w80|5L`k4-q~dq6w6!0`!Q4=_6B#JKOjN@P0gbq-m`< z^{eQz8QknaLwk+2<6<)BhEot_n)3%&HODOS7zRgclF1UoZNHQif(e~3@S+| zJBbGEaCXkSa4s|Av+%2fD(K=oD$78a&*U2-F8CIY4_x2D*}G&L;wITuKi=)_yD-d> z8PY4QU$;Ek6Fz#nGbezo5L~-rX^Uns%IS=(48)|-{U-7)|9P(4KeUT62Vknx4ma%~ zFXUB5)_V?#-syZh$FCYnIB66hh{ok9lbLne6lVf~>?Y94Dazbo9pxu@?_LNe-++dZ z_al$`$8i!~m}8ztPFjn*33%k~R%DUN9n1Yp2m<3)_sC%m%&LGyp?%YdzUfQgTi&lk zS(Fo^_4>A2d+w`e*S_iM-5C z4A7+;Sp>Ma=&mRqf~@zxg2Qo_IM)9#Y-!TUiH5XN$gci3B=3JytN)h`KBFHr>yA9p zWb)mv!Y~VwVS8tyjtI7PzibwSU&cl zU4jXoWPTcY5j)B*1369p1Q*Xi=t+a2e=pd&*vx#W_R3oSVDv2T@_W z&q3PF7=qX+p`1)CmMY-cdKc+51Q8<}bocvj-A-s`YK;?^s}kp_VQb2h=Vq;PYw1_hk_U zB9!kqC_tO`Xk!9ke=~~v1yt=+P5zEbK?Jc{yt7NWSjYaZfx%fxl$>Ca<7EPPHg;k? zs-!jFZT+v5#zZACIrLpxpt$2OZTjP9?z}*03uHr!0Ha;{GmOf&>$Az&@`z&R`0!nH zL4tDl{&ZN&_?aBOGKCitIsSTX(?z%u#MI*g+?lF5aqZTM7H5qLet1@nwEAyqRv)Vb z&lhkc>CVaA~5KnxKZ_98_roDo3 zfp#k7vjA>OtlvHr0)+vuQrYHsai3N$UB8%?ZKNDlv-^i@ue>nYk$)kbF4y*}3PjJn zV{t{iq7Drl4$8pG!7+}qCme>^tNgPLT4 zcRA!VnBL+73fX3E-`1K+Rj;mr3gN7rlb&Q)tn4*Jt@>zfoJL1N=5muYKY+8%`aiUimP5UuEQ%4mtgnp9gm@u& z-|Ri6_F)*wc(ocfmS22?lL_R94wq=`|9vA5a||M3?G^|7vmL=hJO@~;fv#`8ib)!k zObS6L$0xgds^XrNU#QUq*sQ%}0U1a&){``?TR$7JnBKd&k;$xS-X=3o2GdTwN<4v4OW=vWY z*QFkwbzqkZeZkxhq{8vQ4}rmja3)KmcPG9jYUE>gK9UXfGrzPtqHdVmE}n1SCh#;| zq~nAc{TTURx7~k({dM2wv*@ZV?4Zb~P)#!;TFgql2~V!^fk_3q7E~%?yyB{d#lc(! zWv#or4#+Kxq?76@)S>3O>8|C5Ux&0xjKJzs1DPan6(v=a%^*5>jwL5ZOI7BapyeY| zC(5MYC9r8ZQw59A=t|7~$pzN}FTnB^Kxl%HWxqnW-ubsl&47AJOBDF<;8UQ-K96iK zA`AH%0v8(nw&mQ<;ng(}iyb`v!nO#C!dFt;GY=EP#bWr3+ug4-j3cf9U?&M{T}O*O zGi}-X%rN-lMnSAmI`uY^yrd?aQKw`-3$kZ`VScH z0OII@o5j%u^n9GTXyMwgOkJl7aN%sOOK5}E7$#!(ab17G$o(p;fQX!d7OKrP=Y$1 z4rMK;nybdCh{~@LHYIMnVYUK{DB5Khs3pRg7el>h{qO7f@l5t=Mgs7s`yG|A9#CW_ z-B=ImIkV#VK{jaj;~s;Ja;PJ#-#o=#;A4;+d$zCI^L^KSyv5223x}8Ne z(EfGUux(mxKUl!hpS;DGwNfSBAoaq--EFqTxFcSwuWjc}FkmO$(q8XO%OCa$CL>F5 z5!3uBqk8`cd_7@gqaJ4JoP(A16zaesfG&*H#v77>e89ei9}&?-lOmygBY4TemMh{Q zcGc`QUE0?*9Uw;4lArpRcvT$hk!L!lxo`Y_fwul?@9X%33^pVE&duxRSv*C6m8k>ecmrLCwoPat5J_mKNltnC7ghHQnjN`Wi&t`1zie`_KU2Md<*)I z8hLYsJWxzi;zye>H!K-wlp;+Umh}FfZ9N_hhP1c9XkNk+)8f-YnWIC&hVDWs7Q9$b zW7gDY`c!7_kZuyO66|e@4X>8bhSVd%i6!!d)%X*Q4FEf3>Ql#D*`LbhD?}YILb~X6 zCXe#+H1Xn~lNR4S&M@dhVn3O~AYTmfXw~LHEh&1Wt>@|lX-QUDDUlcjMZx!<~d1QVUiZRSr3n@kpcS_Rn)(W1z+{UMyRW1ZP`W|!> z++h(`JFXyK!>0pqD2#@Z`mK=7M=?qhqZeYQv~3I#Zmq}#0r+(o<5cx+!Or;p3Xx{DR2`;k9Hv#%$(Bvk zHia6E78ZmqKp~Tm;UT;}i{?o~so0Myu^E!CM?nKb)uS0E~8;|&O1``mo z3!P5FeJIYzx>-~I^ybbQ1O)hXZY}xF{?mWeq=2=C{cT8GrTbO|s-oR0XQefG*`t|O zKiGkP+WA~<%0nxTz*!M^WOyXxDYog9;&|}TUQ@%tf^jjsoR_omWht zK2$kLx$A+d1A~eDt0h|YJqVsW2-$M$QOCWNDm&4%fmc~sN~nzIq3xHi=G)BUpC5d! zEvs0!nE^i#=zLiR^DtDGmHFGS|dde|MCi z@jaOeWMENV$ZKr}rwbTY(XMSCwr<3-3l57&ZwF(#pObwli7J;m@!Uce?&Y}Ai=5{) zJwo4+Uk%&I4--;kIaMTCGv$1L^JHo%E3xlop**4N)M&vH`MA($hP{`nVk|qDOs(eJ zKrG4#TKD{`1z%LmL!9v!8h8yNjs?0P@f;nvb-YGSAt`03-vW?SBqwJhtkg_r|#n13JT@@60>W*GQ0fWDvE9u~h@^NPRiB+#ht0}` z`^nKl_bJM{ms9|?`nk;DVg80)q(;l;wM6qoUpyjztHwMiu_pA#ZZ9SCcF$P?hKC4$ zd{2me)KH(`4ng{wp`KF0Ii~9tsdpiGUHY0VwAY}=Z_#G?9|XH!S>^8#7ItYEaSA3R z_da`dwV$a5+OfANq2^LB7g?{qtPj!VC|L$n@6KhCuleQ*mwYog7mh(_6j~wF2$n%m zhqNCc4W0tn=DwgmndM2x`MkZ~(X1QOepMb+$M1Fq{|#G9y7-;1S`r{w0!Zfq5bNA2`NPJ|YnK9~SOk@cmj3@#qW>FS?f<(H?E?S+<@tZ3(SC7higb#Cgwm=o zCRKJ$BnWG_c9wSRE=hL9fUwBRiH<=)nB*HVU6>CLUpRQXGt+Ih_Am4q*tA>%Hcn^n zImYwUNw<(2>K4SPsc(Qx6uP;_e@S?jaK{$H8Tu71J51D8s@(KgZg`>O3ERLDAFptA zNHA1TIkGc>5E_*{Gkib;n*{xh19%cBy@&Mg;9AIAYypt0s0u0{anW=p%>_kEa>D*< zgeP3ju6CP1;CNjhw|%AhO0AbH=!{APO0SaqqoS@u?D|WzBckhMTqs5{N%Ie(AbSEb z-xZ-YB(SWCKFftedD*sQ!R~L$GG%W7r-IO^(sbe|tBvTmT7JKtQcU3{h7Toj?s&HS zli1o@VR)N?`QOpU1OCSw7&L(Jvu8<otT^FySg7Lb$%NonbpmX=_zyGXne=~Dt zW}iL##O$+Y&mK0zCM@LGyvgIG!cPZ?ua7ni18N#b`h*D}chc!%+dA2NZ|>rgv>aev z$M?fF3lac3^ab>0>6JDVM74Srvg|z)j1$MQ9j^|xh%~m13)msV;k(_8JDVZF$Uj_A zeIZ&=uWa^URBl*n6EoktM*UveT+?AZ!8ppBj7tPb4U*)&O6K0o3{|cGc(RC5hw^t~ z(cxyeb}yvenHD`d8rcLsp6zqb<4ZzZ5bLO?laQ`ZR}&glSM?{M59=`&LU+oD_P# zNg7A}@^!Y4nL<*o<3MG?a^lEt7;in{Ra03xqvp%H4^-oQDJ|PpdB)=Kt=n2Qx_OH9 zzVI=1ZhK0f(Jf~~;X73GIy1EqqDQZJg_c^Wm_n0vvmB6g;LQhBLpd#}L7dKt)JchO zkh{fqMID)jEol4CMVw7?J=UoY2q>7Zw7n>zpcXR~*IuOAk5OQ-qTLpjroIP5PDR#V z1f>p*eyEKXAopl5r{gA|2U^f+&Rh{oCBu*h$58VKEB%;Lxf9hYLgTrrQ1HW}&M2IB zOl921Zq0k2T}~4z@LBhsKv} z`;S1{#v$G5W5|@6kIhs9>lsJj;9FHUiVU7Ty7qY7j$eo&o8J{F6&rT_4Q8za+cWO|2d zx6kcWr&la+7R4;Wb8ab3eq#Htha{X?h*2*~XE>!ghV_Dp`lF&@UGa=l735=0 z-7-pSK@@o#bIh}$A)lXG@&jpZ(uk*x6huhgvLEXMNt&DLO1WUHbx{%|Z>ffEq%D?) z;z|OTk&M)v#_N#9*PBIsx(0P}pX1PsX{-BO=(FKQijiJ~66?K^38w~WCJC~d%U#J@ z?@oG7Vz5z$Z(icY1{m_a)woQ%ZBx%!LaXd^pw4~jb=>{#^^-Pd6Ju$Sw>2%$fpNlt zjQnmNZ<6TE*v@JcJu|qcq#ns$ASgJzshqllf|7S8ORyB-FuWvu1lfDG^)l&qKFr;)YUKn1ExLn@a z=OwH_wm0F5+BLCPgP`vjFFAU#x3NBGW&_(T&YP8sKj=r+$!l0II)F?>eN*Uo);^I{ zw|#9JNBE>aqqt)1?kVnA5?iZ#0)hTe2P21G8axSi_OUvQM*37WDPF3eais}Cfwwbz z-s8|k9wOBaTOy|U+p)$CTk6yMQ@G@BIWDT^6Kw8u_>(@Pn^ZHoGg{x7>?>exyO_cZtstU8W^(sNf`2OY$zH3LWL%``Vch31 z`H+$jYu_0T=qV{;6?y*!LBAW&2hj&Fui=pDb_LWDNrwCQD(-!*J&u%ll2;nwYk_4g zK!u2lD~>XBBBv&|q9X&w z1j{MfH?54^o5}k5*Hf%vPUxc7Q%y;V@T=v*g>!-q=EEfQ#dtGb=5_P-oy+wR&xcV0 zo6mE$%)v{evIHaLtTQ;qQDN)rhMT@*bC)+tnBX%(g}_ zok*Cm1jNC(a5b4EJ#J6#+|9+mou#}~98oyQ&(ev3dy&+Bj*R;Z^))96#^FU>d#Zt1 zys+zdujvo%jdJD8xQ!_#3XOFfPLiSk5EXj=;UDq23xtM)_W=r zR#h>f+A5*~*k+X9709+H$5G*a&@9{Yd=V-3DwP}Mj)FZr{%OF$`OwMi&KU}ORs*DP zi4ntCdkC_40uHc;`S4hH$f+__1QJ|qP{RafJo_w9*JT19-g-O5K@Vy2os_F*ftE0o z&__WYJ_t?px#!nGrPIQKj2&XW7hD@(y2*U+z2arWZz;!9|{ zx{(qv1k{>XYdAvI??p`&&X=+v#m_|;7zCcN;vv}>2O&PsRh$pMKZ=m#FW$s`&`(%G zxMSDhfs@OGoXtk2ZB|C+$6|lyGkXL_@wom6?{Ily*Tm?UWMf6xqk;90N&B6}$1;0E z`~6I8>t}9AgX>V!br&7zp8chLwZ#q3mY$`O@?5eVKc!6V$VfKu(lm3Bs~PMaG`|jn zi)@_P4fBQQKj+Q10US1KcAU^h-H_#s&m~`kk9*BWFgojH&)TwZm2UXb)b6zIiTb2v z^%0?8afqY3f?982UIgOTz-;kS+`FeQeF&YO;W}kR?CIVr?$cDz9ap{4DRk7yl;E(l zo88h1?6yqv#)k9IH~Gyt!i9B`W3c;q2A3C!H%V)}?M?JpDJt69(deztiRVxOL#V^_))m7;j#0CczNQ74K5kt$>fJM=O?kv zqb*W-PRS0~mimV-&Vv0CNF=((ZM>`^*|36Bdf{C;t1-fA9_%mOE0C{A#5(5fl_&;e zV<}tWb$3x%h z(9gO>GmqLZxh-l!R-mc3TsMCzBvPh=;Yry;?2^Nf00o8n_;y|RJ>6~B4y}=6RF~(b zID@;i@2~n(7q(enqben|(_xC;Hed%Gxdzpgi8YGB>ZI!!IBCvJinrXuR^U$c(d@L3 zrPM}ZQCBGy=3>2rga~t$MW|2H6(i@hmqf!@W1rBeVJ;itLlm^WjY6IOVA&xTA9iL) z9@1azM2f&brVvZ7ojZ&w?`%3EqtI9tEwqF?+dX3-TsJ>kEQLo8kque^BamnenMhWlw&`-vLjTd_oyPaJtI@KMST|E-| z^n%MlVhO~?aMgfNmG*;E$X`f)GSU8q{GxslYpm4Hwyf`>>+_KwJo6w#;m2EB(@H61 zdh?ij+vc2s=H6km9)y+M>?N5h)o6R#r!LS+H_V`ZU;gKiK$4gdcnHQ-C|2zp8y|#Koo+?a2B?O~u!SH%_1+!8DnzfpJG;F!5WLdlGg+6#{ zoBNyN$6tw%EihN3(rzYcXS?a71pdRVp$=sNX(H;1j9H{W%c#G(Z3IC9E3%AFLI|l} zA9dz$^V)Uj6H=0YR`VYem|wJ_y>}odjm6sY48v^YBd)1Z{VUmo9$2=X*JM!2b(9S% zUg&wSaOWi{Z3;fp`J6^{P6L$U~amZ9A<3ssbxwe(eS8FDqhN zfO^z_^Lzy`3;03Nwcj|RLY+m#NeGqzSOxzavH`@ z2DGO7hgE)GNe98c73F|80AF{2@V~6?`$t6*i0E%C?7k8X{MS7N@bLa>h0>qjNq^z^ zS8@?HP2y|O8p$B6z7qSFrAXhGB>sxnf3xlgOzcnVj=mG?^Oe{i4gLP<_V_iif0*q3 z;->hKvwtzs`$x_~JO9o4ZpzMK6Rw3qkMm;<^}IXqZXIav+4faSVyAvaOPQZlF*;JP%5(T!YuDPX8hUH-%HWu?^sC;nC70J*p2EiPP&?b|^25 zs+DXnjEPM2Ay5H+L2~z@v~c|UGEOn?&<6v`P2mTp&YuF@ipe&4Y@WVuLJMGc7gKMn z*Qpbp$tJ28;GywO4T(W-G9D2YqAxbEip0yeR)-VqKC?GhdS4BdFI}Q!H0*p! zVKwz_t-gaEkJTtj#uQEkX!XvsYKQxS!(o%{A<7wwbxTl}8LN&B=^rQ+u*I>T1e=Tp za@5WOQh(kM_iSYZ?Zc3QV#~)DZ{5NO)lj1RMETpKCwcPXN#KxPJGdco+sJuzQrh8Z zrr7vaAJd%qiY}!33>_LQLpcd;D8NQnjo50a!zhU{K(R2X=a+ur)-mF*$j`*;B<5}6p;q1lWae@3=L9^d@?6DoT%j2 z%k$q?b4@ivOEPJ$D$fpAE$Aht)wqT0xr1&`9I{pt6K;By4)vjoOD$; zpjwzfCk$&(PzB~xf&v02-RZI$uI8@ip>Jqi#c~E>x>F(U<7{1Qg{wi&ctc~Bfy5B& z=vRIaYir&xNXPslzIu>WijGeLrXP*tFh39!`v&yTVWtK5t&1if)&i zHLZn14HG4L;g26G^qaOJBWVb|-rPOaoM+k24^(5sw~_lq0nxo+^j3h;2CW6-g;nh$bT zuA$Ajma}ZF>K6BOIvrd%h?#j{$f-29GWQM>m!8E5>CH{~MkWs+Jqn{j&aIKsW}&VU z(MuQJU21<;h#}_ivmfA_SEIy(P&@ZFf%PGsl`Mnp8gN;EwGxMLJ34Vq$Yr;ucqde4 z%GIXl6K$CjlGMl&JEM`|r>toZdtwmh)dqegK|ob&+moa)q^212#KiQ#iEvq^+$&UO z%$BE*3jM~dCSQKoq4AuTQ4k8zRUNjV2-B(c5B%J`gkovvlIZ1!po&)ep2vMlJ09Xp zJb4pRV35u3%?>9u(zP23JE?nnuqh=MUs*Y@$V+WH&fR{(*5Y+-#G3kJ;nxwhwY_mu zC~;s+Z$K*Eu#!$|2Wn3#28pMENlfL|mhH*Z%()%`j})2J?YdBVg8@JBI6 zp^8(|-6A7l55+()_n`y)^0)ZIvMz4hEX#1OYT)D%3&N@^yAviQNJD+x3D`$D`S6Jq&3^^PLAX=R4(H zP@pjQ?s4QKfL^?JMyTKBKA6ATKL7f~`WB#y=xi>=OIfN;22=v_+?MNUkZWW*Y&~z#QwNt z9&k%RvaXJTsEKXuiYbYp+gbp{i#GW^p&C;_EH_H98nEN`gw_ntX7~~nL2uO z0Snszle9O2RNS0tnxnjM)XD+oa-UVIC=btPdT&$-9#eYs~#WL^f{9V;*w zJ)E#x!U3Vq^r`p)G7mHigEn0dOk8!0QDu&+We zblzI2$A!p<{Z3ZcVCf5scUMZ$&+Mp`iqsPk?;~;h(e1@=I7SQHgD2|}93Rx8N{)0T zXl5-PdQvAL+vk%I7(6)~z%@SuUEzgvgtL$??TO05l-_oSUx)8@m2`)3k7PF69JdVz zg8D*J+O_XTNS22j&g{0l=K=B@5!TvomX#InGPQEA36tQnMCZ3+#OIZgbU4GG@z}Wv z!Bo#**&*EAhHd1>@W!(wyIcE^I60`N@VRGw3a>pUXF0a%hLLjNNFZ5Gh-q^P~_*jbJ@I7NEOR&l1{Q>vfsQ>4)2(AyeDlTo~>b>4nt*^G~8 z!9?2iYeyDD13VWtpqLCkX31>Y)x7ko_qC4?E@jqOH;!}TmU(2G_Gv@OdA^y}5}p10 z(G&8~8-b`%>e$jqH@JJ0dP)P_0m0pF+NN|EK0=r@A|&F>Ao6}2 z)UwNtU32Ri)qzouOlLYowHoQe^9HTnJlV$-_x79Eb*)qQ&t5o6clqfD6Y;icITVh% zs^fKdeFzQ7_y6Fl^qR`S|Ak+}+qey#HdM^+(c57wPx9j6cE`qZSXZRgI2m3LhGvSs zU)eN$ZtB+%`5qV6J^W#z@~F`zUhX4=FkUN;I9M1mCkxprIs)Y0`yQiLHEJ9k1) zs7<~rjce=GeSFhSFX8v2JD-txwPjlu^=+i=hmLghN2hEQ4PV!W?Jr%*+(I{<+MCrL zfQ?emL(xQ)96py7*+VqPjPl-*2tGb0%O#mtf>6eJ`c&$(FnkWlp>wPA3V9T%!bxI1 z@(NZrTZP5LJ1*h1jEY6?G2kU%-6fivv&-brHt;lWE)J-s&acHCaI&V@eTndPB}2On z#mgjn|lAELQO5)Mtguv9nmwF%Vek4a8vj7$Y$5P+FG*b0`~iKP(@oEq^Jyw zY4eq&p4$1;1|p&}Upn`vXYPOQoG?)F->Msc58Y8*+yBV{;~TM zEz9qCwoDosri{Zb^KQ&@QTc~`mv=-X8uqWdmW8eFk;3T+*fm+iW>o^~0SUdFy@+wh zao>=imO$Ps8m3&3HdJVJuBUlwHB_}=C}rRJ^vJ(7G2!V;Z6@RU9^T{TkgUbW0gEN> zE+86CK6;DfI$N#WTfEl`q^pr16UR0YHZ(kw5=ZSn4=u8&25IhKCe@}Xx^D1z36;xQ zzG}uxjlw*p2X(_WZxMA%ht=Mfn7N0MK*cRBxYE-;RE;KV{K-TmLN~z-5^)< z+qvkeGg*xC8jeW;8dmB4_Y>aq^IPFi-bX)+7-nu1lZ}tTQi&p&>R(BCbT?RDk$-jh zm39auefWkG)1pZ)q2lWr}z%+HL0E=NBsU` zswAvP-G!*_PEIkT*VS77NVHFB&y@@Mm~tdcS$}s&QjG92B>g@$k@_c9+>?=zev@do z{YYK!;q20L-Fo{*7rL%k5yIy7@hsvjgZhdVy*_Ah&Jwm;BVqzi`v6To-JInoWH<*xQ zdraBNAgbJS1Y;XxwOTquzwYA4Gw!Fr7SxcEjp=l5sIU!XB}js-LCjsF(*74&!R?(k zt0oUfk@-~e0!6)z&y`GOBTRga171^B%X1yyFUfus7>5~aCX@UUhLa192!XuD5I&!1 zOZ+qqfxEf!csNk_Xq2!sq@W*jC&$)hr+Y&6q)OxNX;mpYOGtp7zMvhJ)zPF;l1X8O z93vSs8FQ!?2U1Ba@d`1FxnS;8G%fma8dNGr!X~+`y^mC%AQ$}jD5rKLNed%{;?@%7 zdQ7az1X8qKOQCgSrD!G{lPfwkI5(7s_;~hRWSQOH^sN#(I=bwx2bV$ zfh6*Y==s~;GB=j!IlK@wqFS_15IBPg4GTE8XX2spBOf2Rp!8!7dX6=4DXO}nDZlfH zfM4#}cEbxUvnFjTI0wyak#MRU_0Z1l-(pd?>xxsPMbq$fo_|Gf#-fU68`%sQl%%hE79ryM3*uFQ0c zhOd%tUmyjaW!m!*_?4b+noC#_PdJE6vg4=5j>PEqW4NSfqxCJ+hJhL`soZc#>!{1cxx1~cOK}j@f&JXpb%tdLXj!u*e zVal8pGJACd4oUBza+(0EoY)3awtCNrHb_{V>^8l7(uWEF@|~oA2~M3xIj~ z`||8R$Kyv&@9sBP<`|)vo={^Jeqb2tc3F8QGOXwMp}TFDVE-^QboDV( zld!+G<8|~?5bpw?LMmQCg34XdH=1^ea#Qk?6k60H8N1=(Z!)TK6Js%U@f4F7_)+>I z(e^O-!V5yh;M=90$RtDIa>8D!A{JPMlBz2}G)>Cxl%`u$*gUKWzg9Vt>Z#-6G`oLB zEC1Q80_Ced<*#eWf2~geb3^2Bit4Yz#EB@O2GQ^fc ztJ8W+!KI@Q8oMP!P#?2WL$&zzUii(IKm-Yhq5=<~j9_SmW#T7}H(vMO!QrUt>3YRb=@1F?m`J;vMXGs1nl z5FI4OC1zcw-y* z<6E^Xxx3T#HbGhWfy$yu2^9?0Nb-nqrA?vAs-3GAQTRTM4n4!XnFK?$j}$j?wEIh| zXJQ)#su<9bua97u=B9ItG$xl62Uckiuj~kq%(wL5NLM@ULt#k^Znv$zvl9z_MOYhc z6qnLPMdjp^omd>oD#K^iOK$A=As;Jw!Tx!9m0jwH%kusd-5rqXd@7)k~vTiV7ZPya}GE z-l=3&j*W=5xUB<)io)_ zs;=MsSW!K8RoXx&WhbE!4~B(-bP%oBYvqAi?ILl+EF>m8splVwvlqNzifShc^xDL? z_%lft?0o3z6LgX@o@Wv@Iox8SBAD=b2Nemyx!0HL(yZc8<&w7qbAdS1l^kxxIdVTs zCj^Tz?Q*&Rvbpqt8DTk@ty)7Ji$fG%-zw_(OX}pcS;~8A@o)ayh4r8gz`w zpQ99sr)4T*W;!CINMLvq**H9g(({#!?P@=FkIUQmSRs%<_d-qp73p;!W}SNul1c~> zhyO+;&spbq_{FPomlzwaS;^f?!%+iXLk#nw6vk+SQlUTy`(kUeS+S+a?CY!2Q!D=8@mltIuLpy@)B}% zr;t^R`3cMAcoq?c606a;Ci?v+N<4-G27CxwTLWC6}tz}FRKr$M1{C7 zpr5UTR|h1|n`eX2)8yubQvza@FdG9jrNtI|0HrG^>E?DkT_&!t%ES_ zEPrJFz#=P9m3<0$kE{Gvt07_iJjhMU8}rig)8PXJ<3pOKi)oVLXS;c8AE7##Rd&p5 zdUB=HMzN_fq2IA;vrsWkZ%qdhfOStIzc8vWR}|mf(T9BZv0K6{r`dZf2->lu=%jNp zVI(At;TmFGCz?WZu_d4vO-y)J^e%t|u*~?4HUxrH6bYYbtM1Ea^s`UnA4em=K;-W} zVSi_F5t9*#RRtIjmX83~sef?)`nL%z5SF1lNBh__tOU0Kxy6 z)y2;Q|IY5>M}mK2c=02LfAV|uox?srhyFuZ6=Cxyf-@L@Ge!6V!M~GLf8cNm$L}Ty z0fPUt8O@&w{@tABj|Bf_Qu7B6|9(~zAoxF<)%=;@s{fk9@L%rX-%V`($l<@uY=Y;@ zf!`N1CxGC8E3$&Evi^Qc{6=I2{m9|ph^#+y__s1E@X-BdGV4zq{;kydjo_~w{+$8b zUkE1rF1MoHTvyWr584;@0yD^iU!J-DP$T^_y}#2*|G?mX`5Ff3{lm5VonO=Y|JGX= zp!dbMcLdMP^()ms*$aY61zd7RS=rb)1AMl$ayByp;=cr_O%O=l9|Qpc|GtMGGQi=V z^1|P1{wf6t0wFdy+8aCu3LiQ?{&G&>djA=|VFS+lbNJ~zzdA3Z2H^W203c8r8#y`v zF_E#QgX5PYUnm9R1#ZtTxDeT`jLZ#yGBPWppZiV=u!$0++V-U-lbMmF{WlySXLBRt zKhoe>4anO_8CV-x8iVT~%vqTO9(O<>EN81PNdHPUrP0?iA|rcaa2;>}mm@jZTatZE zBcwSv8d?JBatFX~2M~h;xK5UV^CPw|xo_luOMi(VHGpnQ0ZA}`0|d4#P@kKXnS+g) zjg_6u(%jIMotyJ(;g^5Bn;RhJ0cwds7=dtZmOuoiKwLEClZg4m7+@0=2pasS2rR@f zg8;#rZMj-jFn&Hi2e-yDbhQ7*)z9f55Ewvs4vt?q4lV~1+zogV1gEipj)1QOIDn4> z0IT@ud)=a{{DBrp8wOoug~xQug~-U zT>t;G*Z<3XMFfm7kH9ZZAbcBRz~c`%4aEzTf&G5`5rE^2O~Bgc1>iNy0aP&s3Uomr zOh>>y25=k_kW8ScfZ>c3h=K2Jh=)M=5eP(b9|VF!2kN*2@8(vZd>1GO4~E`AJPEkb z0FqEofcmij4g?VBHV;r&2{;Jgga+DC7Xf*IMyON(j|h-Q2GU3X0Ouxv0b**PEm-0O zGz%E(K-vXJgYjttJ0>LpF@OUC+(!lA+Hv5E=K~^;835oJ7fzsj6NuvgU;_YX2e}Bu$^ZxeKnuttr9cdpW`Og69|3!Nc`S0t)5CY{I0D$p=`%DJFANc=o1YE+NNi;Ar7;*O2oO_E05O$~ J8xT`j{}*aznw0= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 +end +``` +The Swapper Protocol is initialized with a custom predicate function which is then placed in a call to `queryall` inside the Swapper to pick the nodes that are suitable to perform a swap with. The criteria for 'suitability' is described in the further paragraphs. + +The custom predicate function shown above is parametrized with `net` and `c_node` along with the keyword argument `low`, when initializing the Swapper Protocol. `node` remains a variable. This way, the Swapper protocol is passed a predicate function that maps `Int->Bool`. + +Now, we describe the various arguments and their purpose: + +- `net`: The network of registers/nodes representing the graph structure, implemented with the `RegisterNet` data structure. + +- `c_node`: The node in which the Swapper protocol would be running. + +- `node`: As the `queryall` function goes through all the nodes linked with the current node, those nodes are passed to the custom predicate as `node` which returns a `Bool` depending on whether the node is suitable for a swap or not. + +- `low`: The nodes in the grid are numbered as consecutive integers starting from 1. If the Swapper is running at some node n, we want a link closest to Alice and another closest to Bob to perform a swap. We communicate whether we are looking for nodes of the first kind or the latter with the `low` keyword. + +Out of all the links at some node, the suitable ones are picked by computing the difference between the coordinates of the current node with the coordinates of the candidate node. A `low` node should have both of the `x` and `y` coordinate difference positive and vice versa for a non-`low` node. + +As the Swapper gets a list of suitable candidates for a swap in each direction, the one with the furthest distance from the current node is chosen by summing the x distance and y-distance. + +```julia +function choose_node(net, node, arr; low=true) + grid_size = Int(sqrt(size(net.graph)[1])) + return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) +end + +function distance(n, a, b) + x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 + x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 + y1 = a - n*(x1-1) + y2 = b - n*(x2-1) + + return x1 - x2 + y1 - y2 +end +``` + +# Simulation and Visualization + +```julia +n = 6 + +graph = grid([n,n]) + +net = RegisterNet(graph, [Register(8) for i in 1:n^2]) + +sim = get_time_tracker(net) + +for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high + @process eprot() +end + +for i in 2:(size(graph)[1] - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + @process swapper() +end + +for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() +end +``` + +We set up the simulation to run with a 6x6 grid of nodes above. Here, each node has 8 qubit slots. +Each vertical and horizontal edge runs an entanglement generation protocol. Each node in the network runs an entanglement tracker protocol and all of the nodes except the nodes that we're trying to connect, i.e., Alice' and Bob's nodes which are at the diagonal ends of the grid run the swapper protocol. The code that runs and visualizes this simulation is shown below + +```julia +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) +fig = Figure(resolution=(600, 600)) +_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) + +display(fig) + +step_ts = range(0, 10, step=0.1) +record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify(obs) +end +``` + +# Complete Code and Result + +```@example grid +using QuantumSavory + +# For Simulation +using ResumableFunctions +using ConcurrentSim +using QuantumSavory.ProtocolZoo +using Graphs + +# For Plotting +using GLMakie +GLMakie.activate!(inline=false) +using NetworkLayout + +## Custom Predicates + +function check_nodes(net, c_node, node; low=true) + n = Int(sqrt(size(net.graph)[1])) # grid size + c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 + c_y = c_node - n*(c_x-1) + x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 + y = node - n*(x-1) + return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 +end + +# functions for picking the furthest node +function distance(n, a, b) + x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 + x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 + y1 = a - n*(x1-1) + y2 = b - n*(x2-1) + + return x1 - x2 + y1 - y2 +end + +function choose_node(net, node, arr; low=true) + grid_size = Int(sqrt(size(net.graph)[1])) + return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) +end + +## Simulation + +n = 6 + +graph = grid([n,n]) + +net = RegisterNet(graph, [Register(8) for i in 1:n^2]) + +sim = get_time_tracker(net) + +for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high + @process eprot() +end + +for i in 2:(size(graph)[1] - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + @process swapper() +end + +for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() +end + +## Visualization +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) +fig = Figure(resolution=(600, 600)) +_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) + +display(fig) + +step_ts = range(0, 10, step=0.1) +record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify(obs) +end +``` + diff --git a/examples/repeater_grid/repeater_grid.jl b/examples/repeatergrid/repeatergrid.jl similarity index 100% rename from examples/repeater_grid/repeater_grid.jl rename to examples/repeatergrid/repeatergrid.jl From 8d9aeb2165b2fcefd221ee927ff95de13dfc2d9f Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Sun, 31 Mar 2024 15:55:16 -0400 Subject: [PATCH 20/93] Update repeatergrid.md --- docs/src/howto/repeatergrid/repeatergrid.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 71ce079..2e67b29 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -20,7 +20,7 @@ This employs functionality from the `ProtocolZoo` module of QuantumSavory to run - Entanglement Tracker protocol to keep track of/and update the local link state knowledge by querying for Entanglement update messages generated after a BSM is performed by the Swapper protocol -All of the above protocols rely on the query and tagging functionality as described in the Tagging and Querying section in Expanations. +All of the above protocols rely on the query and tagging functionality as described in the Tagging and Querying section in [Explanations](@ref Explanations). Other than that, `ConcurrentSim` and `ResumableFunctions` are used in the backend to run the discrete event simulation. `Graphs` helps with some functionality needed for `RegisterNet` datastructure that forms the grid. `GLMakie` and `NetworkLayout` are used for visualization along with the visualization functionality implemented in QuantumSavory. From f57edc52ae696758397fd6d04890cab30acf3156 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 3 Apr 2024 15:43:35 -0400 Subject: [PATCH 21/93] fixes --- docs/src/howto/repeatergrid/repeatergrid.md | 5 +++++ docs/src/visualizations.md | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 2e67b29..b842370 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -201,5 +201,10 @@ record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify(obs) end + +nothing # hide ``` +```@raw html + +``` \ No newline at end of file diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index e3f3789..3137736 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -65,12 +65,6 @@ fig And here with some extra tag metadata. -```@example vis -tag!(net[2,3], :specialplace, 1, 2) -tag!(net[2,3], :otherdata, 3, 4) -QuantumSavory.showmetadata(fig,ax,plt,2,3) -fig -``` ## The state of locks and various metadata in the network From 4f0e2eed71fe7269408f80b0b3100ef6ea753cdf Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 16 Apr 2024 02:37:20 -0400 Subject: [PATCH 22/93] a bit more inline comments and set number of rounds to infinite --- examples/repeatergrid/repeatergrid.jl | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index 8bd100a..bef33c2 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -11,8 +11,9 @@ using GLMakie GLMakie.activate!(inline=false) using NetworkLayout -## Custom Predicates +## Custom Predicates used for local decisions in the swapper protocol running at each node +"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" function check_nodes(net, c_node, node; low=true) n = Int(sqrt(size(net.graph)[1])) # grid size c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 @@ -22,16 +23,16 @@ function check_nodes(net, c_node, node; low=true) return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 end -# functions for picking the furthest node +"""A "cost" function for choosing the furthest node in the appropriate quadrant.""" function distance(n, a, b) x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 y1 = a - n*(x1-1) y2 = b - n*(x2-1) - return x1 - x2 + y1 - y2 end +"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" function choose_node(net, node, arr; low=true) grid_size = Int(sqrt(size(net.graph)[1])) return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) @@ -39,7 +40,7 @@ end ## Simulation -n = 6 +n = 6 # the size of the square grid network (n × n) graph = grid([n,n]) @@ -47,20 +48,23 @@ net = RegisterNet(graph, [Register(8) for i in 1:n^2]) sim = get_time_tracker(net) +# each edge is capable of generating raw link-level entanglement for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) # TODO needs margin @process eprot() end +# each node except the corners on one of the diagonals is capable of swapping entanglement for i in 2:(size(graph)[1] - 1) l(x) = check_nodes(net, i, x) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end +# each node is running entanglement tracking to keep track of classical data about the entanglement for v in vertices(net) tracker = EntanglementTracker(sim, net, v) @process tracker() From cacaeb62d371c6b4560d1486b70ec96b99ecaa20 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 16 Apr 2024 03:18:14 -0400 Subject: [PATCH 23/93] add entanglement consumer to the grid example --- examples/repeatergrid/repeatergrid.jl | 43 +++++++++++++++++++++------ 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index bef33c2..4f0b1ad 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -41,21 +41,22 @@ end ## Simulation n = 6 # the size of the square grid network (n × n) +regsize = 8 # the size of the quantum registers at each node graph = grid([n,n]) -net = RegisterNet(graph, [Register(8) for i in 1:n^2]) +net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) sim = get_time_tracker(net) # each edge is capable of generating raw link-level entanglement for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) # TODO needs margin + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true, margin=regsize÷2, hardmargin=regsize÷4) @process eprot() end # each node except the corners on one of the diagonals is capable of swapping entanglement -for i in 2:(size(graph)[1] - 1) +for i in 2:(n^2 - 1) l(x) = check_nodes(net, i, x) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) @@ -70,15 +71,39 @@ for v in vertices(net) @process tracker() end -## Visualization -layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) -fig = Figure(resolution=(600, 600)) -_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) +# a mock entanglement consumer between the two corners of the grid +consumer = EntanglementConsumer(sim, net, 1, n^2) +@process consumer() + +# By modifying the `period` of `EntanglementConsumer`, and `rate` of `EntanglerProt`, you can study the effect of different entanglement generation rates on the network + +# Visualization + +fig = Figure(size=(600, 600)) + +# the network part of the visualization +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D +_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + +# the performance log part of the visualization +entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way +ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe +tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] +txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] +Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] +entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") +ylims!(entlogaxis, (-1.04,1.04)) +stem!(entlogaxis, tzzs) +histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") +hist!(histaxis, Δts) display(fig) -step_ts = range(0, 10, step=0.1) +step_ts = range(0, 200, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) - notify(obs) + notify.((obs,entlog)) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) end From 6cdef726f4aebcb0515e464c57cda280cebeb2ba Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 16 Apr 2024 03:37:23 -0400 Subject: [PATCH 24/93] edits for clarity and style in repeatergrid.md --- docs/src/howto/repeatergrid/repeatergrid.md | 28 +++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index b842370..5800777 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -6,23 +6,24 @@ DocTestSetup = quote end ``` -This section provides a detailed walkthrough of how the QuantumSavory.jl can be used to simulate entanglement generation on a network of repeaters. +This section provides a detailed walkthrough of how QuantumSavory.jl can be used to simulate entanglement generation on a network of repeaters where each repeater relies only on local knowledge of the network. -We consider a square grid topology for the network. The registers act as repeater nodes with the ones on the diagonal corners acting as Alice and Bob respectively. +For this example, we consider a square grid topology in which each node is connected to its nearest neighbors. +The registers act as repeater nodes. The nodes on the diagonal corners are Alice and Bob, the two special nodes that the network is trying to entangle through generating link-level entanglement at each edge and performing appropriate swaps at each node. -The goal is to establish entanglement between Alice and Bob by routing entanglement through any of the possible paths(horizontal or vertical) formed by local entanglement links and then swapping those links by performing bell state measurements(BSMs). +The goal is to establish entanglement between Alice and Bob by routing entanglement through any of the possible paths(horizontal or vertical) formed by local entanglement links and then swapping those links by performing entanglement swaps. This employs functionality from the `ProtocolZoo` module of QuantumSavory to run the following Quantum Networking protocols: -- Entangler protocol to produce link level entanglement at each edge in the network +- [`EntanglerProt`](@ref): Entangler protocol to produce link level entanglement at each edge in the network -- Swapper protocol runs at each node except at Alice and Bob nodes, to perform BSMs and extend entanglement links by querying for 2 qubits, each entangled to a different neighbor in the desired direction +- [`SwapperProt`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. -- Entanglement Tracker protocol to keep track of/and update the local link state knowledge by querying for Entanglement update messages generated after a BSM is performed by the Swapper protocol +- [`EntanglementTracker`](@ref) Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperProt` specifically). -All of the above protocols rely on the query and tagging functionality as described in the Tagging and Querying section in [Explanations](@ref Explanations). +All of the above protocols rely on the query and tagging functionality as described in the [Tagging and Querying](@ref tagging-and-querying) section. -Other than that, `ConcurrentSim` and `ResumableFunctions` are used in the backend to run the discrete event simulation. `Graphs` helps with some functionality needed for `RegisterNet` datastructure that forms the grid. `GLMakie` and `NetworkLayout` are used for visualization along with the visualization functionality implemented in QuantumSavory. +Other than that, `ConcurrentSim` and `ResumableFunctions` are used in the backend to run the discrete event simulation. `Graphs` helps with some functionality needed for `RegisterNet` datastructure that forms the grid. `GLMakie` and `NetworkLayout` are used for visualization along with the visualization functionality implemented in `QuantumSavory` itself. # Custom Predicate And Choosing function @@ -36,17 +37,18 @@ function check_nodes(net, c_node, node; low=true) return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 end ``` -The Swapper Protocol is initialized with a custom predicate function which is then placed in a call to `queryall` inside the Swapper to pick the nodes that are suitable to perform a swap with. The criteria for 'suitability' is described in the further paragraphs. -The custom predicate function shown above is parametrized with `net` and `c_node` along with the keyword argument `low`, when initializing the Swapper Protocol. `node` remains a variable. This way, the Swapper protocol is passed a predicate function that maps `Int->Bool`. +The Swapper Protocol is initialized with a custom predicate function which is then placed in a call to `queryall` inside the Swapper to pick the nodes that are suitable to perform a swap with. The criteria for "suitability" is described below. -Now, we describe the various arguments and their purpose: +This predicate function encodes most of the "logic" a local node will be performing. -- `net`: The network of registers/nodes representing the graph structure, implemented with the `RegisterNet` data structure. +The custom predicate function shown above is parametrized with `net` and `c_node` along with the keyword argument `low`, when initializing the Swapper Protocol. This predicate function `Int->Bool` selects the target remote nodes for which a swap is appropriate. The arguments are: + +- `net`: The network of register nodes representing the graph structure, an instance of `RegisterNet`. - `c_node`: The node in which the Swapper protocol would be running. -- `node`: As the `queryall` function goes through all the nodes linked with the current node, those nodes are passed to the custom predicate as `node` which returns a `Bool` depending on whether the node is suitable for a swap or not. +- `node`: As the [`queryall`](@ref) function goes through all the nodes linked with the current node, the custom predicate filters them depending on whether the node is suitable for a swap or not. - `low`: The nodes in the grid are numbered as consecutive integers starting from 1. If the Swapper is running at some node n, we want a link closest to Alice and another closest to Bob to perform a swap. We communicate whether we are looking for nodes of the first kind or the latter with the `low` keyword. From a2206715a278ea4caad78e253a0343c5b43ba486 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Fri, 3 May 2024 14:49:37 -0400 Subject: [PATCH 25/93] Add changes from code review --- docs/make.jl | 1 + docs/src/howto/repeatergrid/repeatergrid.md | 85 +-------------------- examples/repeatergrid/repeatergrid.jl | 2 +- test/test_examples.jl | 6 ++ 4 files changed, 10 insertions(+), 84 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index b2a5483..c40e133 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,6 +4,7 @@ push!(LOAD_PATH,"../src/") using Documenter using DocumenterCitations using QuantumSavory +using QuantumSavory.ProtocolZoo DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 5800777..a90ffd9 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -122,89 +122,8 @@ end # Complete Code and Result -```@example grid -using QuantumSavory - -# For Simulation -using ResumableFunctions -using ConcurrentSim -using QuantumSavory.ProtocolZoo -using Graphs - -# For Plotting -using GLMakie -GLMakie.activate!(inline=false) -using NetworkLayout - -## Custom Predicates - -function check_nodes(net, c_node, node; low=true) - n = Int(sqrt(size(net.graph)[1])) # grid size - c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 - c_y = c_node - n*(c_x-1) - x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 - y = node - n*(x-1) - return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 -end - -# functions for picking the furthest node -function distance(n, a, b) - x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 - x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 - y1 = a - n*(x1-1) - y2 = b - n*(x2-1) - - return x1 - x2 + y1 - y2 -end - -function choose_node(net, node, arr; low=true) - grid_size = Int(sqrt(size(net.graph)[1])) - return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) -end - -## Simulation - -n = 6 - -graph = grid([n,n]) - -net = RegisterNet(graph, [Register(8) for i in 1:n^2]) - -sim = get_time_tracker(net) - -for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high - @process eprot() -end - -for i in 2:(size(graph)[1] - 1) - l(x) = check_nodes(net, i, x) - h(x) = check_nodes(net, i, x; low=false) - cL(arr) = choose_node(net, i, arr) - cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high - @process swapper() -end - -for v in vertices(net) - tracker = EntanglementTracker(sim, net, v) - @process tracker() -end - -## Visualization -layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) -fig = Figure(resolution=(600, 600)) -_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) - -display(fig) - -step_ts = range(0, 10, step=0.1) -record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t - run(sim, t) - notify(obs) -end - -nothing # hide +```@repl +include("../../../../examples/repeatergrid/repeatergrid.jl") ``` ```@raw html diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index 4f0b1ad..a4d1633 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -79,7 +79,7 @@ consumer = EntanglementConsumer(sim, net, 1, n^2) # Visualization -fig = Figure(size=(600, 600)) +fig = Figure(;size=(600, 600)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D diff --git a/test/test_examples.jl b/test/test_examples.jl index 6a78395..403e197 100644 --- a/test/test_examples.jl +++ b/test/test_examples.jl @@ -36,3 +36,9 @@ end include("../examples/congestionchain/1_visualization.jl") end end + +@safetestset "repeatergrid" begin + if get(ENV, "QUANTUMSAVORY_PLOT_TEST","")=="true" + include("../examples/repeatergrid/repeatergrid.jl") + end +end \ No newline at end of file From 67b0fd417e3e6cda297ee4960313b05c05249a7e Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Fri, 3 May 2024 15:11:13 -0400 Subject: [PATCH 26/93] Update repeatergrid.jl --- examples/repeatergrid/repeatergrid.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index a4d1633..c84f0dc 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -8,7 +8,7 @@ using Graphs # For Plotting using GLMakie -GLMakie.activate!(inline=false) +GLMakie.activate!() using NetworkLayout ## Custom Predicates used for local decisions in the swapper protocol running at each node From e9103f235879803c3b915ec2e8d7a82b3f14a3f6 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt <46929125+Abhishek-1Bhatt@users.noreply.github.com> Date: Wed, 8 May 2024 13:49:55 -0400 Subject: [PATCH 27/93] Update Project.toml --- test/Project.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Project.toml b/test/Project.toml index ce51c2e..777b973 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -15,6 +15,7 @@ JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" +NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a" Quantikz = "b0d11df0-eea3-4d79-b4a5-421488cbf74b" QuantumClifford = "0525e862-1e90-11e9-3e4d-1b39d7109de1" QuantumOptics = "6e0679c1-51ea-5a7c-ac74-d61b76210b0c" From fd9fe4fc2027c75ccaaac8e3113a4331c4a06859 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 1 May 2024 18:10:56 -0400 Subject: [PATCH 28/93] make the internals compatible with dictionary for query and tagging --- src/ProtocolZoo/ProtocolZoo.jl | 12 ++++++------ src/networks.jl | 1 + src/queries.jl | 6 +++--- test/test_entanglement_consumer.jl | 1 + 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index de684dc..6d9022d 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -1,7 +1,7 @@ module ProtocolZoo using QuantumSavory -import QuantumSavory: get_time_tracker, Tag +import QuantumSavory: get_time_tracker, Tag, guid using QuantumSavory: Wildcard using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap @@ -190,9 +190,9 @@ end @yield timeout(prot.sim, prot.local_busy_time_post) # tag local node a with EntanglementCounterpart remote_node_idx_b remote_slot_idx_b - tag!(a, EntanglementCounterpart, prot.nodeB, b.idx) + tag!(a, EntanglementCounterpart, prot.nodeB, b.idx; tag_time = now(prot.sim), id = guid()) # tag local node b with EntanglementCounterpart remote_node_idx_a remote_slot_idx_a - tag!(b, EntanglementCounterpart, prot.nodeA, a.idx) + tag!(b, EntanglementCounterpart, prot.nodeA, a.idx; tag_time = now(prot.sim), id = guid()) @debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx)" unlock(a) @@ -260,11 +260,11 @@ end 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) + tag!(q1, EntanglementHistory, tag1[2], tag1[3], tag2[2], tag2[3], q2.idx; tag_time = now(prot.sim), id = guid()) 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) + tag!(q2, EntanglementHistory, tag2[2], tag2[3], tag1[2], tag1[3], q1.idx; tag_time = now(prot.sim), id = guid()) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() @@ -350,7 +350,7 @@ end apply!(localslot, updategate) end # tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx - tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid) + tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid; tag_time=now(prot.sim), id = guid()) unlock(localslot) continue end diff --git a/src/networks.jl b/src/networks.jl index b0f9e53..1d5d6da 100644 --- a/src/networks.jl +++ b/src/networks.jl @@ -14,6 +14,7 @@ struct RegisterNet end function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metadata, directed_edge_metadata) + glcnt[] = 0 # set the global counter of `guid`s to zero whenever a new network is initialized 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) diff --git a/src/queries.jl b/src/queries.jl index 154fa92..92f5825 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -126,8 +126,8 @@ julia> query(r, Int, 4, <(7)) See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) """ -function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {allB} - _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned) +function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true, ref=nothing) where {allB} + _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned, ref=ref) 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, ref=nothing) where {allB, filoB} @@ -282,7 +282,7 @@ end """ $TYPEDSIGNATURES -A [`query`](@ref) for [`RegRef`](@ref) that also deletes the tag from the tag list for the `RegRef`. +A [`query`](@ref) for [`RegRef`](@ref) that also deletes the tag from the tag dictionary for the `Register`. Allows the user to specify order of accessing tags to be FILO or FIFO. """ function querydelete!(ref::RegRef, args...; filo=true, kwa...) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 1dc7b5e..2b8279a 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -13,6 +13,7 @@ end for i in 1:30, n in 3:30 + @show i, n net = RegisterNet([Register(10) for j in 1:n]) sim = get_time_tracker(net) From 2ca487119159ef332bcbba829e8a539f2f83766e Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 18 May 2024 22:58:06 -0400 Subject: [PATCH 29/93] make the protcols aware of decoherence and continue the documentation work from #107 --- docs/src/howto/repeatergrid/repeatergrid.md | 40 +++++++++++++++------ examples/repeatergrid/repeatergrid.jl | 2 +- src/ProtocolZoo/ProtocolZoo.jl | 39 ++++++++------------ src/queries.jl | 29 ++++++++++----- src/states_registers.jl | 4 ++- 5 files changed, 70 insertions(+), 44 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index a90ffd9..4bb7e2d 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -83,17 +83,19 @@ net = RegisterNet(graph, [Register(8) for i in 1:n^2]) sim = get_time_tracker(net) +# each edge is capable of generating raw link-level entanglement for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=5, randomize=true) # A single round doesn't always get the ends entangled, when number of nodes is high + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) @process eprot() end -for i in 2:(size(graph)[1] - 1) +# each node except the corners on one of the diagonals is capable of swapping entanglement +for i in 2:(n^2 - 1) l(x) = check_nodes(net, i, x) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end @@ -107,23 +109,41 @@ We set up the simulation to run with a 6x6 grid of nodes above. Here, each node Each vertical and horizontal edge runs an entanglement generation protocol. Each node in the network runs an entanglement tracker protocol and all of the nodes except the nodes that we're trying to connect, i.e., Alice' and Bob's nodes which are at the diagonal ends of the grid run the swapper protocol. The code that runs and visualizes this simulation is shown below ```julia -layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) -fig = Figure(resolution=(600, 600)) -_, ax, _, obs = registernetplot_axis(fig[1,1], net;registercoords=layout) +fig = Figure(;size=(600, 600)) + +# the network part of the visualization +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D +_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + +# the performance log part of the visualization +entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way +ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe +tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] +txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] +Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] +entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") +ylims!(entlogaxis, (-1.04,1.04)) +stem!(entlogaxis, tzzs) +histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") +hist!(histaxis, Δts) display(fig) -step_ts = range(0, 10, step=0.1) +step_ts = range(0, 200, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) - notify(obs) + notify.((obs,entlog)) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) end + ``` -# Complete Code and Result +# Result ```@repl -include("../../../../examples/repeatergrid/repeatergrid.jl") +include("../../../../examples/repeatergrid/repeatergrid.jl") # hide ``` ```@raw html diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index c84f0dc..344dbbc 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -51,7 +51,7 @@ sim = get_time_tracker(net) # each edge is capable of generating raw link-level entanglement for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true, margin=regsize÷2, hardmargin=regsize÷4) + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) @process eprot() end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 6d9022d..3f8f697 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -1,7 +1,7 @@ module ProtocolZoo using QuantumSavory -import QuantumSavory: get_time_tracker, Tag, guid +import QuantumSavory: get_time_tracker, Tag, iscoherent using QuantumSavory: Wildcard using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap @@ -149,10 +149,6 @@ $TYPEDFIELDS rounds::Int = -1 """whether the protocol should find the first available free slots in the nodes to be entangled or check for free slots randomly from the available slots""" randomize::Bool = false - """Repeated rounds of this protocol may lead to monopolizing all slots of a pair of registers, starving or deadlocking other protocols. This field can be used to always leave a minimum number of slots free if there already exists entanglement between the current pair of nodes.""" - margin::Int = 0 - """Like `margin`, but it is enforced even when no entanglement has been established yet. Usually smaller than `margin`.""" - hardmargin::Int = 0 end """Convenience constructor for specifying `rate` of generation instead of success probability and time""" @@ -170,10 +166,8 @@ end rounds = prot.rounds round = 1 while rounds != 0 - isentangled = !isnothing(query(prot.net[prot.nodeA], EntanglementCounterpart, prot.nodeB, ❓; assigned=true)) - 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) + a = findfreeslot(prot.net[prot.nodeA]; randomize=prot.randomize) + b = findfreeslot(prot.net[prot.nodeB]; randomize=prot.randomize) if isnothing(a) || isnothing(b) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @@ -190,9 +184,9 @@ end @yield timeout(prot.sim, prot.local_busy_time_post) # tag local node a with EntanglementCounterpart remote_node_idx_b remote_slot_idx_b - tag!(a, EntanglementCounterpart, prot.nodeB, b.idx; tag_time = now(prot.sim), id = guid()) + 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; tag_time = now(prot.sim), id = guid()) + tag!(b, EntanglementCounterpart, prot.nodeA, a.idx) @debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx)" unlock(a) @@ -245,7 +239,6 @@ end rounds = prot.rounds round = 1 while rounds != 0 - reg = prot.net[prot.node] qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) if isnothing(qubit_pair) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @@ -260,11 +253,11 @@ end 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; tag_time = now(prot.sim), id = guid()) + tag!(q1, EntanglementHistory, tag1[2], tag1[3], tag2[2], tag2[3], q2.idx) 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; tag_time = now(prot.sim), id = guid()) + tag!(q2, EntanglementHistory, tag2[2], tag2[3], tag1[2], tag1[3], q1.idx) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() @@ -288,9 +281,8 @@ end function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high) reg = net[node] - - low_nodes = queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) - high_nodes = queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) + low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if iscoherent(n.slot; buffer_time=2.0)] + high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if iscoherent(n.slot; buffer_time=2.0)] (isempty(low_nodes) || isempty(high_nodes)) && return nothing il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property @@ -326,7 +318,7 @@ end # 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 - @debug "EntanglementTracker @$(prot.node): Received from $(msg.src).$(msg.tag[3]) | message=`$(msg.tag)`" + @debug "EntanglementTracker @$(prot.node): Received from $(msg.src).$(msg.tag[3]) | message=`$(msg.tag)` | time=$(now(prot.sim))" workwasdone = true (src, (_, pastremotenode, pastremoteslotid, localslotid, newremotenode, newremoteslotid, correction)) = msg localslot = nodereg[localslotid] @@ -350,7 +342,7 @@ end apply!(localslot, updategate) end # tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx - tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid; tag_time=now(prot.sim), id = guid()) + tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid) unlock(localslot) continue end @@ -410,14 +402,14 @@ end end while true query1 = query(prot.net[prot.nodeA], EntanglementCounterpart, prot.nodeB, ❓; locked=false, assigned=true) # TODO Need a `querydelete!` dispatch on `Register` rather than using `query` here followed by `untag!` below - if isnothing(query1) + if isnothing(query1) || !iscoherent(query1.slot; buffer_time=0.5) @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): query on first node found no entanglement" @yield timeout(prot.sim, prot.period) continue else query2 = query(prot.net[prot.nodeB], EntanglementCounterpart, prot.nodeA, query1.slot.idx; locked=false, assigned=true) - - if isnothing(query2) # in case EntanglementUpdate hasn't reached the second node yet, but the first node has the EntanglementCounterpart + # don't really need to check `iscoherent` the second time, but just for safety + if isnothing(query2) || !iscoherent(query2.slot; buffer_time=0.5) # in case EntanglementUpdate hasn't reached the second node yet, but the first node has the EntanglementCounterpart @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): query on second node found no entanglement (yet...)" @yield timeout(prot.sim, prot.period) continue @@ -427,8 +419,7 @@ end q1 = query1.slot q2 = query2.slot @yield lock(q1) & lock(q2) - - @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement" + @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement @ $(now(prot.sim))" 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 diff --git a/src/queries.jl b/src/queries.jl index 92f5825..4c1b6f6 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -6,7 +6,8 @@ See also: [`query`](@ref), [`untag!`](@ref)""" function tag!(ref::RegRef, tag::Tag) id = guid() push!(ref.reg.guids, id) - ref.reg.tag_info[id] = (tag, ref.idx, now(get_time_tracker(ref))) + ref.reg.tag_info[id] = (tag, ref.idx, now(get_time_tracker(ref))) + ref.reg.slot_guid[ref.idx] = id end tag!(ref, tag) = tag!(ref,Tag(tag)) @@ -22,6 +23,7 @@ function untag!(ref::RegRef, id::Int128) # TODO rather slow implementation. See 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) + ref.reg.slot_guid[ref.idx] = -1 nothing end @@ -388,18 +390,29 @@ julia> findfreeslot(reg) |> isnothing true ``` """ -function findfreeslot(reg::Register; randomize=false, margin=0) +function findfreeslot(reg::Register; randomize=false) n_slots = length(reg.staterefs) - freeslots = sum((!isassigned(reg[i]) for i in 1:n_slots)) - if freeslots >= margin - perm = randomize ? randperm : (x->1:x) - for i in perm(n_slots) - slot = reg[i] - islocked(slot) || isassigned(slot) || return slot + perm = randomize ? randperm : (x->1:x) + for i in perm(n_slots) + slot = reg[i] + if !islocked(slot) + if !isassigned(slot) + return slot + elseif !iscoherent(slot) + untag!(slot, reg.slot_guid[slot.idx]) + traceout!(slot) + return slot + end end end end +function iscoherent(slot::RegRef; buffer_time=0.0) + if !isassigned(slot) throw("Slot must be assigned with a quantum state before checking coherence") end + if slot.reg.slot_guid[slot.idx] == -1 throw("Slot hasn't been assigned yet or does not have any active entanglement") end + return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[slot.reg.slot_guid[slot.idx]][3] < slot.reg.retention_times[slot.idx] +end + function Base.isassigned(r::Register,i::Int) # TODO erase r.stateindices[i] != 0 # TODO this also usually means r.staterefs[i] !== nothing - choose one and make things consistent diff --git a/src/states_registers.jl b/src/states_registers.jl index 0d721f5..c5d6256 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -22,11 +22,13 @@ struct Register # TODO better type description locks::Vector{Any} tag_info::Dict{Int128, Tuple{Tag, Int64, Union{Float64, Nothing}}} guids::Vector{Int128} + retention_times::Vector{Float64} + slot_guid::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], Dict{Int128, Tuple{Tag, Int64, Float64}}(), []) + Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), [], fill(5.0, length(traits)), fill(-1, length(traits))) 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))) From 0d279e2c1b9da55b74ab8df38d1c8b7e10174546 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 20 May 2024 16:14:33 -0400 Subject: [PATCH 30/93] Set default retention time to so that we don't break the existing tests --- docs/src/howto/repeatergrid/repeatergrid.md | 5 +++-- examples/repeatergrid/repeatergrid.jl | 2 +- src/states_registers.jl | 11 ++++++++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 4bb7e2d..733b156 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -75,11 +75,12 @@ end # Simulation and Visualization ```julia -n = 6 +n = 6 # the size of the square grid network (n × n) +regsize = 8 # the size of the quantum registers at each node graph = grid([n,n]) -net = RegisterNet(graph, [Register(8) for i in 1:n^2]) +net = RegisterNet(graph, [Register(regsize, fill(5.0, regsize)) for i in 1:n^2]) sim = get_time_tracker(net) diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index 344dbbc..3de1abf 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -45,7 +45,7 @@ regsize = 8 # the size of the quantum registers at each node graph = grid([n,n]) -net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) +net = RegisterNet(graph, [Register(regsize, fill(5.0, regsize)) for i in 1:n^2]) sim = get_time_tracker(net) diff --git a/src/states_registers.jl b/src/states_registers.jl index c5d6256..59fef50 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -22,13 +22,13 @@ struct Register # TODO better type description locks::Vector{Any} tag_info::Dict{Int128, Tuple{Tag, Int64, Union{Float64, Nothing}}} guids::Vector{Int128} - retention_times::Vector{Float64} + retention_times::Base.AbstractVecOrTuple{Float64} slot_guid::Vector{Int128} end -function Register(traits, reprs, bg, sr, si, at) +function Register(traits, reprs, bg, sr, si, at, rt=fill(Inf, length(traits))) env = ConcurrentSim.Simulation() - Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), [], fill(5.0, length(traits)), fill(-1, length(traits))) + Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), [], rt, fill(-1, length(traits))) 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))) @@ -38,6 +38,11 @@ Register(traits) = Register(traits,default_repr.(traits)) Register(nqubits::Int) = Register([Qubit() for _ in 1:nqubits]) Register(nqubits::Int,repr::AbstractRepresentation) = Register(fill(Qubit(),nqubits),fill(repr,nqubits)) Register(nqubits::Int,bg::AbstractBackground) = Register(fill(Qubit(),nqubits),fill(bg,nqubits)) +function Register(nqubits, rt::Base.AbstractVecOrTuple) + @assert length(rt) == nqubits + traits = [Qubit() for _ in 1:nqubits] + Register(traits, default_repr.(traits), fill(nothing, length(traits)), fill(nothing, length(traits)), zeros(Int, length(traits)), zeros(length(traits)), rt) +end """ A reference to a [`Register`](@ref) slot, convenient for use with functions like [`apply!`](@ref), etc. From fae8306de82919151c048dda7e5a34c8ebbd1f23 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 20 May 2024 16:33:36 -0400 Subject: [PATCH 31/93] Use retention time in tests --- test/test_entanglement_consumer.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 2b8279a..b43c723 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -6,19 +6,19 @@ using Test if isinteractive() using Logging - logger = ConsoleLogger(Logging.Warn; meta_formatter=(args...)->(:black,"","")) + logger = ConsoleLogger(Logging.Debug; meta_formatter=(args...)->(:black,"","")) global_logger(logger) println("Logger set to debug") end for i in 1:30, n in 3:30 - @show i, n - net = RegisterNet([Register(10) for j in 1:n]) + regsize = 10 + net = RegisterNet([Register(regsize, fill(5.0, regsize)) for j in 1:n]) sim = get_time_tracker(net) for e in edges(net) - eprot = EntanglerProt(sim, net, e.src, e.dst; rounds=-1, randomize=true, margin=5, hardmargin=3) + eprot = EntanglerProt(sim, net, e.src, e.dst; rounds=-1, randomize=true) @process eprot() end From b6ef8aac54b787ea060942bb07d39e26f56b6570 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 20 May 2024 17:17:09 -0400 Subject: [PATCH 32/93] findfreeslot returns true when slot guid is -1(default) which only happens when using a register outside of a network simulation --- src/queries.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queries.jl b/src/queries.jl index 4c1b6f6..ddd52bf 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -409,7 +409,7 @@ end function iscoherent(slot::RegRef; buffer_time=0.0) if !isassigned(slot) throw("Slot must be assigned with a quantum state before checking coherence") end - if slot.reg.slot_guid[slot.idx] == -1 throw("Slot hasn't been assigned yet or does not have any active entanglement") end + if slot.reg.slot_guid[slot.idx] == -1 return true end return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[slot.reg.slot_guid[slot.idx]][3] < slot.reg.retention_times[slot.idx] end From 3f176af14b3ddbfe688ada0d2be2c48844e06e43 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 20 May 2024 17:26:40 -0400 Subject: [PATCH 33/93] revert change made for debugging --- test/test_entanglement_consumer.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index b43c723..3fdd2a9 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -6,7 +6,7 @@ using Test 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 From f622124775e70c16625172538fb6d43053d0c503 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Fri, 31 May 2024 23:42:06 -0400 Subject: [PATCH 34/93] Add decoherence protocol with asynchronous messaging --- examples/repeatergrid/repeatergrid.jl | 8 +- src/ProtocolZoo/ProtocolZoo.jl | 158 +++++++++++++++++++++---- src/messagebuffer.jl | 2 +- src/queries.jl | 16 +-- src/states_registers.jl | 11 +- src/tags.jl | 2 +- test/test_entanglement_tracker_grid.jl | 2 +- 7 files changed, 148 insertions(+), 51 deletions(-) diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid.jl index 3de1abf..7c31b0b 100644 --- a/examples/repeatergrid/repeatergrid.jl +++ b/examples/repeatergrid/repeatergrid.jl @@ -45,7 +45,7 @@ regsize = 8 # the size of the quantum registers at each node graph = grid([n,n]) -net = RegisterNet(graph, [Register(regsize, fill(5.0, regsize)) for i in 1:n^2]) +net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) sim = get_time_tracker(net) @@ -75,6 +75,12 @@ end consumer = EntanglementConsumer(sim, net, 1, n^2) @process consumer() +# decoherence protocol runs at each node to free up slots that haven't been used past the retention time +for v in vertices(net) + decprot = DecoherenceProt(sim, net, v) + @process decprot() +end + # By modifying the `period` of `EntanglementConsumer`, and `rate` of `EntanglerProt`, you can study the effect of different entanglement generation rates on the network # Visualization diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 045ef19..f340ef7 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -14,7 +14,7 @@ import ResumableFunctions using ResumableFunctions: @resumable import SumTypes -export EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer +export EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer, DecoherenceProt abstract type AbstractProtocol end @@ -118,6 +118,27 @@ Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, ta """ $TYPEDEF +This tag arrives as a message from a remote node's Decoherence Protocol to which the current node used to be entangled, to +update the classical metadata of the entangled slot and empty it + +$TYPEDFIELDS +""" +@kwdef struct EntanglementDelete + "The node that sent the deletion message" + send_node::Int + "The sender's slot containing the decoherent qubit" + send_slot::Int + "The node receiving the message for qubit deletion" + rec_node::Int + "The slot containing decoherent qubit" + rec_slot::Int +end +Base.show(io::IO, tag::EntanglementDelete) = print(io, "Deleted $(tag.send_node).$(tag.send_slot) which was entangled to $(tag.rec_node).$(tag.rec_slot)") +Tag(tag::EntanglementDelete) = Tag(EntanglementDelete, tag.send_node, tag.send_slot, tag.rec_node, tag.rec_slot) + +""" +$TYPEDEF + A protocol that generates entanglement between two nodes. Whenever a pair of empty slots is available, the protocol locks them and starts probabilistic attempts to establish entanglement. @@ -187,7 +208,7 @@ end # 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)" + @debug "EntanglerProt between $(prot.nodeA) and $(prot.nodeB)|round $(round): Entangled .$(a.idx) and .$(b.idx) | time = $(now(prot.sim))" unlock(a) unlock(b) rounds==-1 || (rounds -= 1) @@ -227,6 +248,8 @@ $TYPEDFIELDS retry_lock_time::LT = 0.1 """how many rounds of this protocol to run (`-1` for infinite))""" rounds::Int = -1 + """when synchronizing, the swapper will check the coherence of a swap candidate before commencing a swap, otherwise EntanglementTracker takes care of it through classical message passing""" + sync::Bool = false end #TODO "convenience constructor for the missing things and finish this docstring" @@ -238,7 +261,7 @@ end rounds = prot.rounds round = 1 while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=prot.sync) if isnothing(qubit_pair) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @yield timeout(prot.sim, prot.retry_lock_time) @@ -265,12 +288,12 @@ end # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1`" + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" # send from here to new entanglement counterpart: # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2`" + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" unlock(q1) unlock(q2) rounds==-1 || (rounds -= 1) @@ -278,10 +301,10 @@ end end end -function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high) +function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false) reg = net[node] - low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if iscoherent(n.slot; buffer_time=2.0)] - high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if iscoherent(n.slot; buffer_time=2.0)] + low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot; buffer_time=2.0)] + high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot; buffer_time=2.0)] (isempty(low_nodes) || isempty(high_nodes)) && return nothing il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property @@ -313,14 +336,22 @@ 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, Z), (EntanglementUpdateZ, X)) + for (updatetagsymbol, updategate) in ((EntanglementUpdateX, Z), (EntanglementUpdateZ, X), (EntanglementDelete, nothing)) # 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 + if !isnothing(updategate) + msg = querydelete!(mb, updatetagsymbol, ❓, ❓, ❓, ❓, ❓, ❓) + isnothing(msg) && continue + (src, (_, pastremotenode, pastremoteslotid, localslotid, newremotenode, newremoteslotid, correction)) = msg + else + msg = querydelete!(mb, updatetagsymbol, ❓, ❓, ❓, ❓) + isnothing(msg) && continue + (src, (_, pastremotenode, pastremoteslotid, _, localslotid)) = msg + end + @debug "EntanglementTracker @$(prot.node): Received from $(msg.src).$(msg.tag[3]) | message=`$(msg.tag)` | time=$(now(prot.sim))" workwasdone = true - (src, (_, pastremotenode, pastremoteslotid, localslotid, newremotenode, newremoteslotid, correction)) = msg localslot = nodereg[localslotid] + # Check if the local slot is still present and believed to be entangled. # We will need to perform a correction operation due to the swap, # but there will be no message forwarding necessary. @@ -336,15 +367,20 @@ 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.") end - # Pauli frame correction gate - if correction==2 - apply!(localslot, updategate) + if !isnothing(updategate) #EntanglementUpdate + # 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) + else # EntanglementDelete + traceout!(localslot) end - # tag local with updated EntanglementCounterpart new_remote_node new_remote_slot_idx - tag!(localslot, EntanglementCounterpart, newremotenode, newremoteslotid) unlock(localslot) continue end + # If not, check if we have a record of the entanglement being swapped to a different remote node, # and forward the message to that node. history = querydelete!(localslot, EntanglementHistory, @@ -355,13 +391,26 @@ end # @debug "tracker @$(prot.node) history: $(history) | msg: $msg" _, _, _, 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) - put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) + if !isnothing(updategate) + 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) + put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) + else # We have a delete message but the qubit was swapped so add a tag and forward to swapped node + @debug "EntanglementTracker @$(prot.node): history=`$(history)` | message=`$msg` | Sending to $(whoweswappedwith_node).$(whoweswappedwith_slotidx)" + msghist = Tag(updatetagsymbol, pastremotenode, pastremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx) + tag!(localslot, updatetagsymbol, prot.node, localslot, whoweswappedwith_node, whoweswappedwith_slotidx) + put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) + end + continue + end + + if !isnothing(querydelete!(localslot, EntanglementDelete, prot.node, localslot.idx, pastremotenode, pastremoteslotid)) #deletion from both sides of the swap, deletion msg when both qubits of a pair are deleted, or when EU arrives after ED at swap node with two simultaneous swaps and deletion on one side + @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled" 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.") + + 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` or `EntanglementDelete` tags). This is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.") end end @debug "EntanglementTracker @$(prot.node): Starting message wait at $(now(prot.sim)) with MessageBuffer containing: $(mb.buffer)" @@ -402,14 +451,14 @@ end end while true query1 = query(prot.net[prot.nodeA], EntanglementCounterpart, prot.nodeB, ❓; locked=false, assigned=true) # TODO Need a `querydelete!` dispatch on `Register` rather than using `query` here followed by `untag!` below - if isnothing(query1) || !iscoherent(query1.slot; buffer_time=0.5) + if isnothing(query1) @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): query on first node found no entanglement" @yield timeout(prot.sim, prot.period) continue else query2 = query(prot.net[prot.nodeB], EntanglementCounterpart, prot.nodeA, query1.slot.idx; locked=false, assigned=true) # don't really need to check `iscoherent` the second time, but just for safety - if isnothing(query2) || !iscoherent(query2.slot; buffer_time=0.5) # in case EntanglementUpdate hasn't reached the second node yet, but the first node has the EntanglementCounterpart + if isnothing(query2) # in case EntanglementUpdate hasn't reached the second node yet, but the first node has the EntanglementCounterpart @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): query on second node found no entanglement (yet...)" @yield timeout(prot.sim, prot.period) continue @@ -420,7 +469,7 @@ end q2 = query2.slot @yield lock(q1) & lock(q2) - @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement @ $(now(prot.sim))" + @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement between .$(q1.idx) and .$(q2.idx) @ $(now(prot.sim))" 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 @@ -436,4 +485,63 @@ end end end +""" +$TYPEDEF + +A protocol running at a node, checking periodically for any decoherent entanglement and emptying such slots. + +$FIELDS +""" +@kwdef struct DecoherenceProt <: AbstractProtocol + """time-and-schedule-tracking instance from `ConcurrentSim`""" + sim::Simulation + """a network graph of registers""" + net::RegisterNet + """the vertex index of node A""" + node::Int + """time period between successive queries on the node""" + period::Float64 = 0.1 + """Time after which a slot is emptied""" + retention_time::Float64 = 5.0 + """No messages are sent when this is set to true""" + sync::Bool = false +end + +function DecoherenceProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return DecoherenceProt(;sim, net, node, kwargs...) +end + +@resumable function (prot::DecoherenceProt)() + reg = prot.net[prot.node] + while true + for slot in reg + @yield lock(slot) + info = query(slot, EntanglementCounterpart, ❓, ❓) + if isnothing(info) unlock(slot);continue end + if now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + traceout!(slot) + msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) + tag!(slot, msg) + (prot.sync) || put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) + @debug "DecoherenceProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" + end + + #delete old history tags + info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + end + + #delete old EntanglementDelete tags + info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + end + unlock(slot) + end + @yield timeout(prot.sim, prot.period) + end +end + end # module diff --git a/src/messagebuffer.jl b/src/messagebuffer.jl index c89501d..75cacdd 100644 --- a/src/messagebuffer.jl +++ b/src/messagebuffer.jl @@ -16,7 +16,7 @@ end function Base.put!(cf::ChannelForwarder, tag::Tag) # shortest path calculated by Graphs.a_star nexthop = first(a_star(cf.net.graph, cf.src, cf.dst)) - @debug "ChannelForwarder: Forwarding message from node $(nexthop.src) to node $(nexthop.dst) | message=$(tag)| end destination=$(cf.dst)" + # @debug "ChannelForwarder: Forwarding message from node $(nexthop.src) to node $(nexthop.dst) | message=$(tag)| end destination=$(cf.dst)" put!(channel(cf.net, cf.src=>nexthop.dst; permit_forward=false), tag_types.Forward(tag, cf.dst)) end diff --git a/src/queries.jl b/src/queries.jl index 5d18aea..0acb95b 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -7,8 +7,6 @@ function tag!(ref::RegRef, tag::Tag) id = guid() push!(ref.reg.guids, id) ref.reg.tag_info[id] = (tag, ref.idx, now(get_time_tracker(ref))) - - ref.reg.slot_guid[ref.idx] = id end tag!(ref, tag) = tag!(ref,Tag(tag)) @@ -24,7 +22,6 @@ 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) - ref.reg.slot_guid[ref.idx] = -1 end @@ -399,21 +396,14 @@ function findfreeslot(reg::Register; randomize=false) perm = randomize ? randperm : (x->1:x) for i in perm(n_slots) slot = reg[i] - if !islocked(slot) - if !isassigned(slot) - return slot - elseif !iscoherent(slot) - untag!(slot, reg.slot_guid[slot.idx]) - traceout!(slot) - return slot - end + if !islocked(slot) && !isassigned(slot) + return slot end end end -function iscoherent(slot::RegRef; buffer_time=0.0) +function iscoherent(slot::RegRef, id::Int; buffer_time=0.0) if !isassigned(slot) throw("Slot must be assigned with a quantum state before checking coherence") end - if slot.reg.slot_guid[slot.idx] == -1 return true end return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[slot.reg.slot_guid[slot.idx]][3] < slot.reg.retention_times[slot.idx] end diff --git a/src/states_registers.jl b/src/states_registers.jl index 59fef50..0d721f5 100644 --- a/src/states_registers.jl +++ b/src/states_registers.jl @@ -22,13 +22,11 @@ struct Register # TODO better type description locks::Vector{Any} tag_info::Dict{Int128, Tuple{Tag, Int64, Union{Float64, Nothing}}} guids::Vector{Int128} - retention_times::Base.AbstractVecOrTuple{Float64} - slot_guid::Vector{Int128} end -function Register(traits, reprs, bg, sr, si, at, rt=fill(Inf, length(traits))) +function Register(traits, reprs, bg, sr, si, at) env = ConcurrentSim.Simulation() - Register(traits, reprs, bg, sr, si, at, [ConcurrentSim.Resource(env) for _ in traits], Dict{Int128, Tuple{Tag, Int64, Float64}}(), [], rt, fill(-1, length(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))) @@ -38,11 +36,6 @@ Register(traits) = Register(traits,default_repr.(traits)) Register(nqubits::Int) = Register([Qubit() for _ in 1:nqubits]) Register(nqubits::Int,repr::AbstractRepresentation) = Register(fill(Qubit(),nqubits),fill(repr,nqubits)) Register(nqubits::Int,bg::AbstractBackground) = Register(fill(Qubit(),nqubits),fill(bg,nqubits)) -function Register(nqubits, rt::Base.AbstractVecOrTuple) - @assert length(rt) == nqubits - traits = [Qubit() for _ in 1:nqubits] - Register(traits, default_repr.(traits), fill(nothing, length(traits)), fill(nothing, length(traits)), zeros(Int, length(traits)), zeros(length(traits)), rt) -end """ A reference to a [`Register`](@ref) slot, convenient for use with functions like [`apply!`](@ref), etc. diff --git a/src/tags.jl b/src/tags.jl index 374d3e7..4097a9d 100644 --- a/src/tags.jl +++ b/src/tags.jl @@ -8,7 +8,7 @@ julia> Tag(:sometagdescriptor, 1, 2, -3) SymbolIntIntInt(:sometagdescriptor, 1, 2, -3)::Tag ``` -A tag can have a custom `DataType` as first argument, in which case additional customability in printing is available. E.g. consider the [`EntanglementHistory`] tag used to track how pairs were entangled before a swap happened. +A tag can have a custom `DataType` as first argument, in which case additional customizability in printing is available. E.g. consider the [`EntanglementHistory`] tag used to track how pairs were entangled before a swap happened. ```jldoctest julia> using QuantumSavory.ProtocolZoo: EntanglementHistory diff --git a/test/test_entanglement_tracker_grid.jl b/test/test_entanglement_tracker_grid.jl index a21977b..52c3467 100644 --- a/test/test_entanglement_tracker_grid.jl +++ b/test/test_entanglement_tracker_grid.jl @@ -9,7 +9,7 @@ using Test 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 From 7ef0172217f0fc5f41a1e655444410d25e192dcd Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Fri, 31 May 2024 23:52:17 -0400 Subject: [PATCH 35/93] Some leftover cleanup from previous style of code --- test/test_entanglement_consumer.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 8ffeb58..512e3bd 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -15,7 +15,7 @@ end for n in 3:30 regsize = 10 - net = RegisterNet([Register(regsize, fill(5.0, regsize)) for j in 1:n]) + net = RegisterNet([Register(regsize) for j in 1:n]) sim = get_time_tracker(net) for e in edges(net) From eb2f96d5d4ee048f3c09cafceed5e9d30d430d94 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 1 Jun 2024 17:16:55 -0400 Subject: [PATCH 36/93] synchronous mode for decoherence protocol --- docs/src/howto/repeatergrid/repeatergrid.md | 2 +- ...{repeatergrid.jl => repeatergrid_async.jl} | 0 examples/repeatergrid/repeatergrid_sync.jl | 115 ++++++++++++++++++ src/ProtocolZoo/ProtocolZoo.jl | 12 +- src/queries.jl | 4 +- test/test_examples.jl | 3 +- 6 files changed, 128 insertions(+), 8 deletions(-) rename examples/repeatergrid/{repeatergrid.jl => repeatergrid_async.jl} (100%) create mode 100644 examples/repeatergrid/repeatergrid_sync.jl diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 733b156..f53b8e6 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -144,7 +144,7 @@ end # Result ```@repl -include("../../../../examples/repeatergrid/repeatergrid.jl") # hide +include("../../../../examples/repeatergrid/repeatergrid_async.jl") # hide ``` ```@raw html diff --git a/examples/repeatergrid/repeatergrid.jl b/examples/repeatergrid/repeatergrid_async.jl similarity index 100% rename from examples/repeatergrid/repeatergrid.jl rename to examples/repeatergrid/repeatergrid_async.jl diff --git a/examples/repeatergrid/repeatergrid_sync.jl b/examples/repeatergrid/repeatergrid_sync.jl new file mode 100644 index 0000000..780c0c5 --- /dev/null +++ b/examples/repeatergrid/repeatergrid_sync.jl @@ -0,0 +1,115 @@ +using QuantumSavory + +# For Simulation +using ResumableFunctions +using ConcurrentSim +using QuantumSavory.ProtocolZoo +using Graphs + +# For Plotting +using GLMakie +GLMakie.activate!() +using NetworkLayout + +## Custom Predicates used for local decisions in the swapper protocol running at each node + +"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" +function check_nodes(net, c_node, node; low=true) + n = Int(sqrt(size(net.graph)[1])) # grid size + c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 + c_y = c_node - n*(c_x-1) + x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 + y = node - n*(x-1) + return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 +end + +"""A "cost" function for choosing the furthest node in the appropriate quadrant.""" +function distance(n, a, b) + x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 + x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 + y1 = a - n*(x1-1) + y2 = b - n*(x2-1) + return x1 - x2 + y1 - y2 +end + +"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" +function choose_node(net, node, arr; low=true) + grid_size = Int(sqrt(size(net.graph)[1])) + return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) +end + +## Simulation + +n = 6 # the size of the square grid network (n × n) +regsize = 8 # the size of the quantum registers at each node + +graph = grid([n,n]) + +net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) + +sim = get_time_tracker(net) + +# each edge is capable of generating raw link-level entanglement +for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) + @process eprot() +end + +# each node except the corners on one of the diagonals is capable of swapping entanglement +for i in 2:(n^2 - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, sync=true) + @process swapper() +end + +# each node is running entanglement tracking to keep track of classical data about the entanglement +for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() +end + +# a mock entanglement consumer between the two corners of the grid +consumer = EntanglementConsumer(sim, net, 1, n^2) +@process consumer() + +# decoherence protocol runs at each node to free up slots that haven't been used past the retention time +for v in vertices(net) + decprot = DecoherenceProt(sim, net, v; sync=true) + @process decprot() +end + +# By modifying the `period` of `EntanglementConsumer`, and `rate` of `EntanglerProt`, you can study the effect of different entanglement generation rates on the network + +# Visualization + +fig = Figure(;size=(600, 600)) + +# the network part of the visualization +layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D +_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + +# the performance log part of the visualization +entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way +ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe +tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] +txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] +Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] +entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") +ylims!(entlogaxis, (-1.04,1.04)) +stem!(entlogaxis, tzzs) +histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") +hist!(histaxis, Δts) + +display(fig) + +step_ts = range(0, 200, step=0.1) +record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify.((obs,entlog)) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) +end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index f340ef7..0c2b3dc 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -250,6 +250,10 @@ $TYPEDFIELDS rounds::Int = -1 """when synchronizing, the swapper will check the coherence of a swap candidate before commencing a swap, otherwise EntanglementTracker takes care of it through classical message passing""" sync::Bool = false + """what is the oldest a qubit should be to be picked for a swap""" + retention_time::Float64 = 5.0 + """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" + buffer_time::Float64 = 0.5 end #TODO "convenience constructor for the missing things and finish this docstring" @@ -261,7 +265,7 @@ end rounds = prot.rounds round = 1 while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=prot.sync) + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=prot.sync, buffer_time=prot.buffer_time, retention_time=prot.retention_time) if isnothing(qubit_pair) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @yield timeout(prot.sim, prot.retry_lock_time) @@ -301,10 +305,10 @@ end end end -function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false) +function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false, buffer_time=nothing, retention_time=nothing) reg = net[node] - low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot; buffer_time=2.0)] - high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot; buffer_time=2.0)] + low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot, buffer_time, retention_time, n.id)] + high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot, buffer_time, retention_time, n.id)] (isempty(low_nodes) || isempty(high_nodes)) && return nothing il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property diff --git a/src/queries.jl b/src/queries.jl index 0acb95b..ecf5771 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -402,9 +402,9 @@ function findfreeslot(reg::Register; randomize=false) end end -function iscoherent(slot::RegRef, id::Int; buffer_time=0.0) +function iscoherent(slot::RegRef, buffer_time, retention_time, id) if !isassigned(slot) throw("Slot must be assigned with a quantum state before checking coherence") end - return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[slot.reg.slot_guid[slot.idx]][3] < slot.reg.retention_times[slot.idx] + return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[id][3] < retention_time end diff --git a/test/test_examples.jl b/test/test_examples.jl index 403e197..5afdff9 100644 --- a/test/test_examples.jl +++ b/test/test_examples.jl @@ -39,6 +39,7 @@ end @safetestset "repeatergrid" begin if get(ENV, "QUANTUMSAVORY_PLOT_TEST","")=="true" - include("../examples/repeatergrid/repeatergrid.jl") + include("../examples/repeatergrid/repeatergrid_async.jl") + include("../examples/repeatergrid/repeatergrid_sync.jl") end end \ No newline at end of file From 6653db5b331028a20bafab009228c962443ad16b Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 3 Jun 2024 10:39:29 -0400 Subject: [PATCH 37/93] Separate Swappers based on the use of DecoherenceProt, and fix naming convention --- examples/repeatergrid/repeatergrid_sync.jl | 2 +- src/ProtocolZoo/ProtocolZoo.jl | 107 ++++++++++++++++++--- 2 files changed, 95 insertions(+), 14 deletions(-) diff --git a/examples/repeatergrid/repeatergrid_sync.jl b/examples/repeatergrid/repeatergrid_sync.jl index 780c0c5..e330553 100644 --- a/examples/repeatergrid/repeatergrid_sync.jl +++ b/examples/repeatergrid/repeatergrid_sync.jl @@ -61,7 +61,7 @@ for i in 2:(n^2 - 1) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, sync=true) + swapper = SwapperShedder(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 0c2b3dc..ca88f05 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -14,7 +14,7 @@ import ResumableFunctions using ResumableFunctions: @resumable import SumTypes -export EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer, DecoherenceProt +export EntanglerProt, SwapperProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt abstract type AbstractProtocol end @@ -223,11 +223,12 @@ end """ $TYPEDEF -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If a decoherence protcol is used, then communications would be done with asynchronous messaging +through the `EntanglementTracker`. Keeps(considers) all the swap candidates without verifying there decoherence status $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}} +@kwdef struct SwapperKeeper{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 """a network graph of registers""" @@ -248,24 +249,20 @@ $TYPEDFIELDS retry_lock_time::LT = 0.1 """how many rounds of this protocol to run (`-1` for infinite))""" rounds::Int = -1 - """when synchronizing, the swapper will check the coherence of a swap candidate before commencing a swap, otherwise EntanglementTracker takes care of it through classical message passing""" - sync::Bool = false - """what is the oldest a qubit should be to be picked for a swap""" - retention_time::Float64 = 5.0 - """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" - buffer_time::Float64 = 0.5 end +const SwapperProt = SwapperKeeper + #TODO "convenience constructor for the missing things and finish this docstring" -function SwapperProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return SwapperProt(;sim, net, node, kwargs...) +function SwapperKeeper(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return SwapperKeeper(;sim, net, node, kwargs...) end -@resumable function (prot::SwapperProt)() +@resumable function (prot::SwapperKeeper)() rounds = prot.rounds round = 1 while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=prot.sync, buffer_time=prot.buffer_time, retention_time=prot.retention_time) + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) if isnothing(qubit_pair) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @yield timeout(prot.sim, prot.retry_lock_time) @@ -316,6 +313,90 @@ function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_h return (low_nodes[il], high_nodes[ih]) end +""" +$TYPEDEF + +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. Rejects the swap candidates that are about to decohere. + +$TYPEDFIELDS +""" +@kwdef struct SwapperShedder{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 + """a network graph of registers""" + net::RegisterNet + """the vertex of the node where swapping is happening""" + node::Int + """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" + nodeL::NL = ❓ + """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" + nodeH::NH = ❓ + """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ + chooseL::CL = random_index + """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ + chooseH::CH = random_index + """fixed "busy time" duration immediately before starting entanglement generation attempts""" + local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in + """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" + retry_lock_time::LT = 0.1 + """how many rounds of this protocol to run (`-1` for infinite))""" + rounds::Int = -1 + """what is the oldest a qubit should be to be picked for a swap""" + retention_time::Float64 = 5.0 + """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" + buffer_time::Float64 = 0.5 +end + + +#TODO "convenience constructor for the missing things and finish this docstring" +function SwapperShedder(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return SwapperShedder(;sim, net, node, kwargs...) +end + +@resumable function (prot::SwapperShedder)() + rounds = prot.rounds + round = 1 + while rounds != 0 + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=true, buffer_time=prot.buffer_time, retention_time=prot.retention_time) + if isnothing(qubit_pair) + isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO + @yield timeout(prot.sim, prot.retry_lock_time) + continue + end + + (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, 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, 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) + + uptotime!((q1, q2), now(prot.sim)) + swapcircuit = LocalEntanglementSwap() + xmeas, zmeas = swapcircuit(q1, q2) + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) + put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) + put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + unlock(q1) + unlock(q2) + rounds==-1 || (rounds -= 1) + round += 1 + end +end + """ $TYPEDEF From e3682cf68856ba99bc37cc8017fe90cdd1e8aa25 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 3 Jun 2024 10:42:00 -0400 Subject: [PATCH 38/93] typo --- src/ProtocolZoo/ProtocolZoo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index ca88f05..ce5c8a1 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -223,7 +223,7 @@ end """ $TYPEDEF -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If a decoherence protcol is used, then communications would be done with asynchronous messaging +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If a decoherence protocol is used, then communications would be done with asynchronous messaging through the `EntanglementTracker`. Keeps(considers) all the swap candidates without verifying there decoherence status $TYPEDFIELDS From 7d67e76af817f9e59e00ba03e567273043a5ff2f Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 3 Jun 2024 15:41:07 -0400 Subject: [PATCH 39/93] Completely rename SwapperProt to SwapperKeeper --- docs/src/howto/repeatergrid/repeatergrid.md | 4 ++-- examples/firstgenrepeater_v2/2_swapper_example.jl | 2 +- examples/firstgenrepeater_v2/setup.jl | 2 +- examples/repeatergrid/repeatergrid_async.jl | 2 +- src/ProtocolZoo/ProtocolZoo.jl | 4 +--- test/test_entanglement_consumer.jl | 4 ++-- test/test_entanglement_tracker.jl | 6 +++--- test/test_entanglement_tracker_grid.jl | 6 +++--- 8 files changed, 14 insertions(+), 16 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index f53b8e6..50d98a4 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -17,7 +17,7 @@ This employs functionality from the `ProtocolZoo` module of QuantumSavory to run - [`EntanglerProt`](@ref): Entangler protocol to produce link level entanglement at each edge in the network -- [`SwapperProt`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. +- [`SwapperKeeper`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. - [`EntanglementTracker`](@ref) Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperProt` specifically). @@ -96,7 +96,7 @@ for i in 2:(n^2 - 1) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) + swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end diff --git a/examples/firstgenrepeater_v2/2_swapper_example.jl b/examples/firstgenrepeater_v2/2_swapper_example.jl index 0301c31..068a34f 100644 --- a/examples/firstgenrepeater_v2/2_swapper_example.jl +++ b/examples/firstgenrepeater_v2/2_swapper_example.jl @@ -20,7 +20,7 @@ for (;src, dst) in edges(network) @process eprot() end for node in vertices(network) - sprot = SwapperProt(sim, network, node; nodeL = <(node), nodeH = >(node), chooseL = argmin, chooseH = argmax) + sprot = SwapperKeeper(sim, network, node; nodeL = <(node), nodeH = >(node), chooseL = argmin, chooseH = argmax) @process sprot() end diff --git a/examples/firstgenrepeater_v2/setup.jl b/examples/firstgenrepeater_v2/setup.jl index edc69ae..d0703c2 100644 --- a/examples/firstgenrepeater_v2/setup.jl +++ b/examples/firstgenrepeater_v2/setup.jl @@ -14,7 +14,7 @@ using QuantumSavory # Predefined useful circuits using QuantumSavory.CircuitZoo: EntanglementSwap, Purify2to1 -using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperProt +using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperKeeper ## # Create a handful of qubit registers in a chain diff --git a/examples/repeatergrid/repeatergrid_async.jl b/examples/repeatergrid/repeatergrid_async.jl index 7c31b0b..6e9f3c2 100644 --- a/examples/repeatergrid/repeatergrid_async.jl +++ b/examples/repeatergrid/repeatergrid_async.jl @@ -61,7 +61,7 @@ for i in 2:(n^2 - 1) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) + swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index ce5c8a1..c70578c 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -14,7 +14,7 @@ import ResumableFunctions using ResumableFunctions: @resumable import SumTypes -export EntanglerProt, SwapperProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt +export EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt abstract type AbstractProtocol end @@ -251,8 +251,6 @@ $TYPEDFIELDS rounds::Int = -1 end -const SwapperProt = SwapperKeeper - #TODO "convenience constructor for the missing things and finish this docstring" function SwapperKeeper(sim::Simulation, net::RegisterNet, node::Int; kwargs...) return SwapperKeeper(;sim, net, node, kwargs...) diff --git a/test/test_entanglement_consumer.jl b/test/test_entanglement_consumer.jl index 512e3bd..e800446 100644 --- a/test/test_entanglement_consumer.jl +++ b/test/test_entanglement_consumer.jl @@ -1,5 +1,5 @@ using QuantumSavory -using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer +using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperKeeper, EntanglementTracker, EntanglementConsumer using Graphs using ConcurrentSim using Test @@ -24,7 +24,7 @@ for n in 3:30 end for v in 2:n-1 - sprot = SwapperProt(sim, net, v; nodeL = <(v), nodeH = >(v), chooseL = argmin, chooseH = argmax, rounds = -1) + sprot = SwapperKeeper(sim, net, v; nodeL = <(v), nodeH = >(v), chooseL = argmin, chooseH = argmax, rounds = -1) @process sprot() end diff --git a/test/test_entanglement_tracker.jl b/test/test_entanglement_tracker.jl index afc4230..2dde3b0 100644 --- a/test/test_entanglement_tracker.jl +++ b/test/test_entanglement_tracker.jl @@ -45,8 +45,8 @@ for i in 1:10 @test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false - swapper2 = SwapperProt(sim, net, 2; nodeL = <(2), nodeH = >(2), chooseL = argmin, chooseH = argmax, rounds = 1) - swapper3 = SwapperProt(sim, net, 3; nodeL = <(3), nodeH = >(3), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper2 = SwapperKeeper(sim, net, 2; nodeL = <(2), nodeH = >(2), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper3 = SwapperKeeper(sim, net, 3; nodeL = <(3), nodeH = >(3), chooseL = argmin, chooseH = argmax, rounds = 1) @process swapper2() @process swapper3() run(sim, 80) @@ -100,7 +100,7 @@ for i in 1:30, n in 2:30 @process eprot() end for j in 2:n-1 - swapper = SwapperProt(sim, net, j; nodeL = <(j), nodeH = >(j), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper = SwapperKeeper(sim, net, j; nodeL = <(j), nodeH = >(j), chooseL = argmin, chooseH = argmax, rounds = 1) @process swapper() end run(sim, 200) diff --git a/test/test_entanglement_tracker_grid.jl b/test/test_entanglement_tracker_grid.jl index 52c3467..fe45032 100644 --- a/test/test_entanglement_tracker_grid.jl +++ b/test/test_entanglement_tracker_grid.jl @@ -109,7 +109,7 @@ for path in paths h = x->check_nodes(net, path[i], x; low=false) cL = arr->choose_node(net, path[i], arr) cH = arr->choose_node(net, path[i], arr; low=false) - swapper = SwapperProt(sim, net, path[i]; nodeL=l, nodeH=h, chooseL=cL, chooseH=cH, rounds=1) + swapper = SwapperKeeper(sim, net, path[i]; nodeL=l, nodeH=h, chooseL=cL, chooseH=cH, rounds=1) @process swapper() end run(sim, 200) @@ -163,7 +163,7 @@ for n in 4:10 h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high @process swapper() end @@ -201,7 +201,7 @@ for n in 4:10 h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high @process swapper() end From d31c72a42fe44a5d1bb575d9ade6ca8d09a35923 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 4 Jun 2024 11:07:09 -0400 Subject: [PATCH 40/93] Fix a little mess from yesterday's merge --- src/ProtocolZoo/ProtocolZoo.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index f7653b9..e05455f 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -14,7 +14,13 @@ import ResumableFunctions using ResumableFunctions: @resumable import SumTypes -export EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt +export + # protocols + EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, + # tags + EntanglementCounterpart, EntanglementHistory, EntanglementUpdateX, EntanglementUpdateZ, + # from Switches + SimpleSwitchDiscreteProt, SwitchRequest abstract type AbstractProtocol end From 98cded535914ab023a5e8a95235ea22ec16aa676 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 4 Jun 2024 11:21:55 -0400 Subject: [PATCH 41/93] more fixes and cleanup --- src/ProtocolZoo/ProtocolZoo.jl | 10 +++++----- src/ProtocolZoo/switches.jl | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index e05455f..efc91d6 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -305,12 +305,12 @@ end # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" # send from here to new entanglement counterpart: # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" unlock(q1) unlock(q2) rounds==-1 || (rounds -= 1) @@ -400,12 +400,12 @@ end # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" # send from here to new entanglement counterpart: # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" unlock(q1) unlock(q2) rounds==-1 || (rounds -= 1) @@ -576,7 +576,7 @@ end @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement between .$(q1.idx) and .$(q2.idx) @ $(now(prot.sim))" 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 do we need to add EntanglementHistory and should that be a different EntanglementHistory since the current one is specifically for Swapper # 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)) ob2 = real(observable((q1, q2), X⊗X)) diff --git a/src/ProtocolZoo/switches.jl b/src/ProtocolZoo/switches.jl index 05fb3e8..b03fdd5 100644 --- a/src/ProtocolZoo/switches.jl +++ b/src/ProtocolZoo/switches.jl @@ -312,7 +312,7 @@ perform swaps to connect them and decrement the backlog counter. function _switch_run_swaps(prot, match) @debug "Switch $(prot.switchnode) performs swaps for client pairs $([(prot.clientnodes[i], prot.clientnodes[j]) for (i,j) in match])" for (i,j) in match - swapper = SwapperProt( # TODO be more careful about how much simulated time this takes + swapper = SwapperKeeper( # TODO be more careful about how much simulated time this takes sim=prot.sim, net=prot.net, node=prot.switchnode, nodeL=prot.clientnodes[i], nodeH=prot.clientnodes[j], rounds=1 From 7961189a239106e719dbc4dde74d95d435b9b33f Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 4 Jun 2024 11:37:34 -0400 Subject: [PATCH 42/93] fix --- src/ProtocolZoo/ProtocolZoo.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index efc91d6..447b541 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -16,7 +16,7 @@ import SumTypes export # protocols - EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, + EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt, # tags EntanglementCounterpart, EntanglementHistory, EntanglementUpdateX, EntanglementUpdateZ, # from Switches From afc200c99152f5bcd3894c04b59f9d37443f9888 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 11 Jun 2024 11:07:24 -0400 Subject: [PATCH 43/93] Apply changes from code review --- docs/make.jl | 1 - .../1a_async_interactive_visualization.jl | 63 +++++ .../1b_async_wglmakie_interactive.jl | 140 ++++++++++ .../2a_sync_interactive_visualization.jl.jl | 63 +++++ .../2b_sync_wglmakie_interactive.jl | 139 ++++++++++ examples/repeatergrid/Project.toml | 0 examples/repeatergrid/Readme.md | 0 examples/repeatergrid/repeatergrid_async.jl | 115 -------- examples/repeatergrid/repeatergrid_sync.jl | 115 -------- examples/repeatergrid/setup.jl | 91 ++++++ src/ProtocolZoo/ProtocolZoo.jl | 35 ++- src/messagebuffer.jl | 2 +- src/networks.jl | 1 - src/queries.jl | 258 ++++++++---------- .../test_protocolzoo_entanglement_consumer.jl | 2 +- ...t_protocolzoo_entanglement_tracker_grid.jl | 2 +- 16 files changed, 635 insertions(+), 392 deletions(-) create mode 100644 examples/repeatergrid/1a_async_interactive_visualization.jl create mode 100644 examples/repeatergrid/1b_async_wglmakie_interactive.jl create mode 100644 examples/repeatergrid/2a_sync_interactive_visualization.jl.jl create mode 100644 examples/repeatergrid/2b_sync_wglmakie_interactive.jl create mode 100644 examples/repeatergrid/Project.toml create mode 100644 examples/repeatergrid/Readme.md delete mode 100644 examples/repeatergrid/repeatergrid_async.jl delete mode 100644 examples/repeatergrid/repeatergrid_sync.jl create mode 100644 examples/repeatergrid/setup.jl diff --git a/docs/make.jl b/docs/make.jl index c40e133..b2a5483 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,7 +4,6 @@ push!(LOAD_PATH,"../src/") using Documenter using DocumenterCitations using QuantumSavory -using QuantumSavory.ProtocolZoo DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl new file mode 100644 index 0000000..ad9fd3e --- /dev/null +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -0,0 +1,63 @@ +using GLMakie + +include("setup.jl") + +sim, net, graph, consumer, params... = prepare_simulation() + +fig = Figure(;size=(800, 600)) + +# the network part of the visualization +layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D +_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + +# the performance log part of the visualization +entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way +ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe +tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] +txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] +Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] +entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") +ylims!(entlogaxis, (-1.04,1.04)) +stem!(entlogaxis, tzzs) +histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") +hist!(histaxis, Δts) + +# sliders +sg = SliderGrid( + fig[3,1], + (label="Probability of success of Entanglement generation at each attempt", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Local busy time for swapper", + range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + (label="Wait time after failure to lock qubits for a swap", + range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), + (label="Retention time for an unused qubit", + range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), + (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), + (label="Period of time between subsequent queries at the consumer", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Period of time between subsequent queries at the DecoherenceProtocol", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + + width = 600, + tellheight = false) + +for (param, slider) in zip(params, sg.sliders) + on(slider.value) do val + param[] = val + end +end + + +display(fig) + +step_ts = range(0, 1000, step=0.1) +record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify.((obs,entlog)) + notify.(params) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) +end diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl new file mode 100644 index 0000000..540d475 --- /dev/null +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -0,0 +1,140 @@ +using WGLMakie +WGLMakie.activate!() +import Bonito +using Markdown + +include("setup.jl") + +const custom_css = Bonito.DOM.style("ul {list-style: circle !important;}") # TODO remove after fix of bug in JSServe https://github.com/SimonDanisch/JSServe.jl/issues/178 + +function prepare_singlerun() + # Prepare all of the simulation components (while all visualization components are prepared in the rest of this function) + sim, net, graph, consumer, params... = prepare_simulation() + + # Prepare the main figure + fig = Figure(size=(1200, 800)) + # the network part of the visualization + layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D + _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + + # the performance log part of the visualization + entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way + ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe + tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] + txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] + Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] + entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") + ylims!(entlogaxis, (-1.04,1.04)) + stem!(entlogaxis, tzzs) + histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") + hist!(histaxis, Δts) + + # sliders + sg = SliderGrid( + fig[3,1], + (label="Probability of success of Entanglement generation at each attempt", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Local busy time for swapper", + range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + (label="Wait time after failure to lock qubits for a swap", + range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), + (label="Retention time for an unused qubit", + range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), + (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), + (label="Period of time between subsequent queries at the consumer", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Period of time between subsequent queries at the DecoherenceProtocol", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + + width = 600, + tellheight = false) + + for (param, slider) in zip(params, sg.sliders) + on(slider.value) do val + param[] = val + end + end + + return sim, net, obs, entlog, entlogaxis, histaxis, fig, params +end + +# All the calls that happen in the main event loop of the simulation, +# encapsulated here so that we can conveniently pause the simulation from the WGLMakie app. +function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, running) + step_ts = range(0, 1000, step=0.1) + for t in step_ts + run(sim, t) + notify.((obs,entlog)) + notify.(params) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) + end + running[] = nothing +end + +# +landing = Bonito.App() do + + sim, net, obs, entlog, entlogaxis, histaxis, fig, params = prepare_singlerun() + + running = Observable{Any}(false) + fig[4,1] = buttongrid = GridLayout(tellwidth = false) + buttongrid[1,1] = b = Makie.Button(fig, label = @lift(isnothing($running) ? "Done" : $running ? "Running..." : "Run once"), height=30, tellwidth=false) + + on(b.clicks) do _ + if !running[] + running[] = true + end + end + on(running) do r + if r + Threads.@spawn begin + continue_singlerun!( + sim, obs, entlog, params, entlogaxis, histaxis, running) + end + end + end + + + content = md""" + Pick simulation settings and hit run (see below for technical details). + + $(fig.scene) + + # Simulations of Entanglement Distribution in a Grid with Asynchronous Messaging + + The end nodes(Alice and Bob) are located on the diagonal corners of the grid. + Each node runs control protocols like entanglement tracking and handling of outdated entangled pairs through decoherence protocol. + Each horizontal and vertical edge between adjacent/neighboring nodes runs an entanglement generation protocol. + All nodes except the end nodes run the swapper protocol to establish entanglement between Alice and Bob by extending the raw link level entanglement between each pair of nodes + through a series of swaps until it reaches Alice and Bob. + At the end nodes we run an entanglement consumer protocol which consumes the epr pair between them and logs the fidelity of the final epr pair along with the time it took to generate it. + Both of these are presented in the top and bottom graphs on the right above respectively. + + All the classical information about the entanglement status of nodes after swaps or deletions(decoherence protocols) is communicated through + asynchronous messaging with the help of tags and queries and handled by the entanglement tracker. With this the swapper protocol(`SwapperKeeper`) + considers all the proposed candidates for a swap, relying on the messages sent by the decoherence protocol to the entanglement tracker to delete any qubits that might have taken part + in a swap, while their entangled pair got deleted due to decoherence. If this happens all the qubits involved in the swap need to be discarded by forwarding the deletion message to the + respective nodes. + + [See and modify the code for this simulation on github.](https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/repeatergrid/1b_async_wglmakie_interactive.jl) + """ + return Bonito.DOM.div(Bonito.MarkdownCSS, Bonito.Styling, custom_css, content) +end; + +# +# Serve the Makie app + +isdefined(Main, :server) && close(server); +port = parse(Int, get(ENV, "ASYNC_GRID_PORT", "8888")) +interface = get(ENV, "ASYNC_GRID_IP", "127.0.0.1") +proxy_url = get(ENV, "ASYNC_GRID_PROXY", "") +server = Bonito.Server(interface, port; proxy_url); +Bonito.HTTPServer.start(server) +Bonito.route!(server, "/" => landing); + +## + +wait(server) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl.jl new file mode 100644 index 0000000..966920b --- /dev/null +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl.jl @@ -0,0 +1,63 @@ +using GLMakie + +include("setup.jl") + +sim, net, graph, consumer, params... = prepare_simulation(;sync=true) + +fig = Figure(;size=(800, 600)) + +# the network part of the visualization +layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D +_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + +# the performance log part of the visualization +entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way +ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe +tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] +txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] +Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] +entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") +ylims!(entlogaxis, (-1.04,1.04)) +stem!(entlogaxis, tzzs) +histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") +hist!(histaxis, Δts) + +# sliders +sg = SliderGrid( + fig[3,1], + (label="Probability of success of Entanglement generation at each attempt", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Local busy time for swapper", + range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + (label="Wait time after failure to lock qubits for a swap", + range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), + (label="Retention time for an unused qubit", + range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), + (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), + (label="Period of time between subsequent queries at the consumer", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Period of time between subsequent queries at the DecoherenceProtocol", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + + width = 600, + tellheight = false) + +for (param, slider) in zip(params, sg.sliders) + on(slider.value) do val + param[] = val + end +end + + +display(fig) + +step_ts = range(0, 1000, step=0.1) +record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t + run(sim, t) + notify.((obs,entlog)) + notify.(params) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) +end diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl new file mode 100644 index 0000000..aabaf64 --- /dev/null +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -0,0 +1,139 @@ +using WGLMakie +WGLMakie.activate!() +import Bonito +using Markdown + +include("setup.jl") + +const custom_css = Bonito.DOM.style("ul {list-style: circle !important;}") # TODO remove after fix of bug in JSServe https://github.com/SimonDanisch/JSServe.jl/issues/178 + +function prepare_singlerun() + # Prepare all of the simulation components (while all visualization components are prepared in the rest of this function) + sim, net, graph, consumer, params... = prepare_simulation(;sync=true) + + # Prepare the main figure + fig = Figure(size=(1200, 800)) + # the network part of the visualization + layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D + _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) + + # the performance log part of the visualization + entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way + ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe + tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] + txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] + Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] + entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") + ylims!(entlogaxis, (-1.04,1.04)) + stem!(entlogaxis, tzzs) + histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") + hist!(histaxis, Δts) + + # sliders + sg = SliderGrid( + fig[3,1], + (label="Probability of success of Entanglement generation at each attempt", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Local busy time for swapper", + range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + (label="Wait time after failure to lock qubits for a swap", + range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), + (label="Retention time for an unused qubit", + range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), + (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), + (label="Period of time between subsequent queries at the consumer", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + (label="Period of time between subsequent queries at the DecoherenceProtocol", + range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + + width = 600, + tellheight = false) + + for (param, slider) in zip(params, sg.sliders) + on(slider.value) do val + param[] = val + end + end + + return sim, net, obs, entlog, entlogaxis, histaxis, fig, params +end + +# All the calls that happen in the main event loop of the simulation, +# encapsulated here so that we can conveniently pause the simulation from the WGLMakie app. +function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, running) + step_ts = range(0, 1000, step=0.1) + for t in step_ts + run(sim, t) + notify.((obs,entlog)) + notify.(params) + ylims!(entlogaxis, (-1.04,1.04)) + xlims!(entlogaxis, max(0,t-50), 1+t) + autolimits!(histaxis) + end + running[] = nothing +end + +# +landing = Bonito.App() do + + sim, net, obs, entlog, entlogaxis, histaxis, fig, params = prepare_singlerun() + + running = Observable{Any}(false) + fig[4,1] = buttongrid = GridLayout(tellwidth = false) + buttongrid[1,1] = b = Makie.Button(fig, label = @lift(isnothing($running) ? "Done" : $running ? "Running..." : "Run once"), height=30, tellwidth=false) + + on(b.clicks) do _ + if !running[] + running[] = true + end + end + on(running) do r + if r + Threads.@spawn begin + continue_singlerun!( + sim, obs, entlog, params, entlogaxis, histaxis, running) + end + end + end + + + content = md""" + Pick simulation settings and hit run (see below for technical details). + + $(fig.scene) + + # Simulations of Entanglement Distribution in a Grid with Synchronization + + The end nodes(Alice and Bob) are located on the diagonal corners of the grid. + Each node runs control protocols like entanglement tracking and handling of outdated entangled pairs through decoherence protocol. + Each horizontal and vertical edge between adjacent/neighboring nodes runs an entanglement generation protocol. + All nodes except the end nodes run the swapper protocol to establish entanglement between Alice and Bob by extending the raw link level entanglement between each pair of nodes + through a series of swaps until it reaches Alice and Bob. + At the end nodes we run an entanglement consumer protocol which consumes the epr pair between them and logs the fidelity of the final epr pair along with the time it took to generate it. + Both of these are presented in the top and bottom graphs on the right above respectively. + + All the classical information about the entanglement status of nodes after swaps is communicated through + asynchronous messaging with the help of tags and queries and handled by the entanglement tracker. The decoherence protocol doesn't generate + any messages here. Hence, the swapper protocol (SwapperShedder) checks every proposed candidate to be coherent before its used. Thus the swapper and decoherence protocol + interact in a synchronous manner here. + + [See and modify the code for this simulation on github.](https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/repeatergrid/2b_sync_wglmakie_interactive.jl) + """ + return Bonito.DOM.div(Bonito.MarkdownCSS, Bonito.Styling, custom_css, content) +end; + +# +# Serve the Makie app + +isdefined(Main, :server) && close(server); +port = parse(Int, get(ENV, "SYNC_GRID_PORT", "8888")) +interface = get(ENV, "SYNC_GRID_IP", "127.0.0.1") +proxy_url = get(ENV, "SYNC_GRID_PROXY", "") +server = Bonito.Server(interface, port; proxy_url); +Bonito.HTTPServer.start(server) +Bonito.route!(server, "/" => landing); + +## + +wait(server) diff --git a/examples/repeatergrid/Project.toml b/examples/repeatergrid/Project.toml new file mode 100644 index 0000000..e69de29 diff --git a/examples/repeatergrid/Readme.md b/examples/repeatergrid/Readme.md new file mode 100644 index 0000000..e69de29 diff --git a/examples/repeatergrid/repeatergrid_async.jl b/examples/repeatergrid/repeatergrid_async.jl deleted file mode 100644 index 6e9f3c2..0000000 --- a/examples/repeatergrid/repeatergrid_async.jl +++ /dev/null @@ -1,115 +0,0 @@ -using QuantumSavory - -# For Simulation -using ResumableFunctions -using ConcurrentSim -using QuantumSavory.ProtocolZoo -using Graphs - -# For Plotting -using GLMakie -GLMakie.activate!() -using NetworkLayout - -## Custom Predicates used for local decisions in the swapper protocol running at each node - -"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" -function check_nodes(net, c_node, node; low=true) - n = Int(sqrt(size(net.graph)[1])) # grid size - c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 - c_y = c_node - n*(c_x-1) - x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 - y = node - n*(x-1) - return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 -end - -"""A "cost" function for choosing the furthest node in the appropriate quadrant.""" -function distance(n, a, b) - x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 - x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 - y1 = a - n*(x1-1) - y2 = b - n*(x2-1) - return x1 - x2 + y1 - y2 -end - -"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" -function choose_node(net, node, arr; low=true) - grid_size = Int(sqrt(size(net.graph)[1])) - return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) -end - -## Simulation - -n = 6 # the size of the square grid network (n × n) -regsize = 8 # the size of the quantum registers at each node - -graph = grid([n,n]) - -net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) - -sim = get_time_tracker(net) - -# each edge is capable of generating raw link-level entanglement -for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) - @process eprot() -end - -# each node except the corners on one of the diagonals is capable of swapping entanglement -for i in 2:(n^2 - 1) - l(x) = check_nodes(net, i, x) - h(x) = check_nodes(net, i, x; low=false) - cL(arr) = choose_node(net, i, arr) - cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) - @process swapper() -end - -# each node is running entanglement tracking to keep track of classical data about the entanglement -for v in vertices(net) - tracker = EntanglementTracker(sim, net, v) - @process tracker() -end - -# a mock entanglement consumer between the two corners of the grid -consumer = EntanglementConsumer(sim, net, 1, n^2) -@process consumer() - -# decoherence protocol runs at each node to free up slots that haven't been used past the retention time -for v in vertices(net) - decprot = DecoherenceProt(sim, net, v) - @process decprot() -end - -# By modifying the `period` of `EntanglementConsumer`, and `rate` of `EntanglerProt`, you can study the effect of different entanglement generation rates on the network - -# Visualization - -fig = Figure(;size=(600, 600)) - -# the network part of the visualization -layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D -_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) - -# the performance log part of the visualization -entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way -ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe -tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] -txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] -Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] -entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") -ylims!(entlogaxis, (-1.04,1.04)) -stem!(entlogaxis, tzzs) -histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") -hist!(histaxis, Δts) - -display(fig) - -step_ts = range(0, 200, step=0.1) -record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t - run(sim, t) - notify.((obs,entlog)) - ylims!(entlogaxis, (-1.04,1.04)) - xlims!(entlogaxis, max(0,t-50), 1+t) - autolimits!(histaxis) -end diff --git a/examples/repeatergrid/repeatergrid_sync.jl b/examples/repeatergrid/repeatergrid_sync.jl deleted file mode 100644 index e330553..0000000 --- a/examples/repeatergrid/repeatergrid_sync.jl +++ /dev/null @@ -1,115 +0,0 @@ -using QuantumSavory - -# For Simulation -using ResumableFunctions -using ConcurrentSim -using QuantumSavory.ProtocolZoo -using Graphs - -# For Plotting -using GLMakie -GLMakie.activate!() -using NetworkLayout - -## Custom Predicates used for local decisions in the swapper protocol running at each node - -"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" -function check_nodes(net, c_node, node; low=true) - n = Int(sqrt(size(net.graph)[1])) # grid size - c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 - c_y = c_node - n*(c_x-1) - x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 - y = node - n*(x-1) - return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 -end - -"""A "cost" function for choosing the furthest node in the appropriate quadrant.""" -function distance(n, a, b) - x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 - x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 - y1 = a - n*(x1-1) - y2 = b - n*(x2-1) - return x1 - x2 + y1 - y2 -end - -"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" -function choose_node(net, node, arr; low=true) - grid_size = Int(sqrt(size(net.graph)[1])) - return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) -end - -## Simulation - -n = 6 # the size of the square grid network (n × n) -regsize = 8 # the size of the quantum registers at each node - -graph = grid([n,n]) - -net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) - -sim = get_time_tracker(net) - -# each edge is capable of generating raw link-level entanglement -for (;src, dst) in edges(net) - eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) - @process eprot() -end - -# each node except the corners on one of the diagonals is capable of swapping entanglement -for i in 2:(n^2 - 1) - l(x) = check_nodes(net, i, x) - h(x) = check_nodes(net, i, x; low=false) - cL(arr) = choose_node(net, i, arr) - cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperShedder(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) - @process swapper() -end - -# each node is running entanglement tracking to keep track of classical data about the entanglement -for v in vertices(net) - tracker = EntanglementTracker(sim, net, v) - @process tracker() -end - -# a mock entanglement consumer between the two corners of the grid -consumer = EntanglementConsumer(sim, net, 1, n^2) -@process consumer() - -# decoherence protocol runs at each node to free up slots that haven't been used past the retention time -for v in vertices(net) - decprot = DecoherenceProt(sim, net, v; sync=true) - @process decprot() -end - -# By modifying the `period` of `EntanglementConsumer`, and `rate` of `EntanglerProt`, you can study the effect of different entanglement generation rates on the network - -# Visualization - -fig = Figure(;size=(600, 600)) - -# the network part of the visualization -layout = SquareGrid(cols=:auto, dx=10.0, dy=-10.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D -_, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) - -# the performance log part of the visualization -entlog = Observable(consumer.log) # Observables are used by Makie to update the visualization in real-time in an automated reactive way -ts = @lift [e[1] for e in $entlog] # TODO this needs a better interface, something less cluncky, maybe also a whole Makie recipe -tzzs = @lift [Point2f(e[1],e[2]) for e in $entlog] -txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] -Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] -entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") -ylims!(entlogaxis, (-1.04,1.04)) -stem!(entlogaxis, tzzs) -histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") -hist!(histaxis, Δts) - -display(fig) - -step_ts = range(0, 200, step=0.1) -record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t - run(sim, t) - notify.((obs,entlog)) - ylims!(entlogaxis, (-1.04,1.04)) - xlims!(entlogaxis, max(0,t-50), 1+t) - autolimits!(histaxis) -end diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl new file mode 100644 index 0000000..53c61f3 --- /dev/null +++ b/examples/repeatergrid/setup.jl @@ -0,0 +1,91 @@ +using QuantumSavory +using QuantumSavory.ProtocolZoo +using Graphs +using ConcurrentSim +using ResumableFunctions +using NetworkLayout + +# Predicate function for swap decisions +"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" +function check_nodes(net, c_node, node; low=true) + n = Int(sqrt(size(net.graph)[1])) # grid size + c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 + c_y = c_node - n*(c_x-1) + x = node%n == 0 ? node ÷ n : (node ÷ n) + 1 + y = node - n*(x-1) + return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 +end + +#Choosing function to pick from swap candidates +"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" +function choose_node(net, node, arr; low=true) + grid_size = Int(sqrt(size(net.graph)[1])) + return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) +end + +"""A "cost" function for choosing the furthest node in the appropriate quadrant.""" +function distance(n, a, b) + x1 = a%n == 0 ? a ÷ n : (a ÷ n) + 1 + x2 = b%n == 0 ? b ÷ n : (b ÷ n) + 1 + y1 = a - n*(x1-1) + y2 = b - n*(x2-1) + return x1 - x2 + y1 - y2 +end + +# Simulation setup + +function prepare_simulation(;sync=false) + n = 6 # number of nodes on each row and column for a 6x6 grid + regsize = 20 # memory slots in each node + + # The graph of network connectivity + graph = grid([n,n]) + + net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) + sim = get_time_tracker(net) + + ##Setup the networking protocols running between each of the nodes + + # Entanglement generation + succ_prob = Observable(0.001) + for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true, success_prob=succ_prob[]) + @process eprot() + end + + # Swapper + local_busy_time = Observable(0.0) + retry_lock_time = Observable(0.1) + retention_time = Observable(5.0) + buffer_time = Observable(0.5) + + for i in 2:(n^2 - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = if sync SwapperShedder(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, local_busy_time=local_busy_time[], retry_lock_time=retry_lock_time[], retention_time=retention_time[], buffer_time=buffer_time[]) + else SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, local_busy_time=local_busy_time[], retry_lock_time=retry_lock_time[]) end + @process swapper() + end + + # Entanglement Tracking + for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() + end + + # Entanglement usage/consumption by the network end nodes + period_cons = Observable(0.1) + consumer = EntanglementConsumer(sim, net, 1, n^2; period=period_cons[]) + @process consumer() + + # decoherence protocol runs at each node to free up slots that haven't been used past the retention time + period_dec = Observable(0.1) + for v in vertices(net) + decprot = DecoherenceProt(sim, net, v; sync=sync, period=period_dec[]) # TODO default and slider for retention_time + @process decprot() + end + + return sim, net, graph, consumer, succ_prob, local_busy_time, retry_lock_time, retention_time, buffer_time, period_cons, period_dec +end \ No newline at end of file diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 447b541..39ad9d5 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -178,6 +178,10 @@ $TYPEDFIELDS attempts::Int = -1 """whether the protocol should find the first available free slots in the nodes to be entangled or check for free slots randomly from the available slots""" randomize::Bool = false + """Repeated rounds of this protocol may lead to monopolizing all slots of a pair of registers, starving or deadlocking other protocols. This field can be used to always leave a minimum number of slots free if there already exists entanglement between the current pair of nodes.""" + margin::Int = 0 + """Like `margin`, but it is enforced even when no entanglement has been established yet. Usually smaller than `margin`.""" + hardmargin::Int = 0 end """Convenience constructor for specifying `rate` of generation instead of success probability and time""" @@ -195,8 +199,10 @@ end rounds = prot.rounds round = 1 while rounds != 0 - a = findfreeslot(prot.net[prot.nodeA]; randomize=prot.randomize) - b = findfreeslot(prot.net[prot.nodeB]; randomize=prot.randomize) + isentangled = !isnothing(query(prot.net[prot.nodeA], EntanglementCounterpart, prot.nodeB, ❓; assigned=true)) + 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. \nGot:\n1. \t $a \n2.\t $b \n retrying..." @@ -241,8 +247,12 @@ end """ $TYPEDEF -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If a decoherence protocol is used, then communications would be done with asynchronous messaging -through the `EntanglementTracker`. Keeps(considers) all the swap candidates without verifying there decoherence status +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the decoherence prtocol, [`DecoherenceProt`](@ref) is used, then communications about the +decoherence status of qubit would be done with asynchronous messaging through the [`EntanglementTracker`](@ref). Thus, `SwapperKeeper` keeps(considers) all the swap candidates +without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the decoherence protocol and forwarding the deletion messages +to the swapped nodes after the swap. + +See also: [`SwapperShedder`](@ref) $TYPEDFIELDS """ @@ -332,7 +342,11 @@ end """ $TYPEDEF -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. Rejects the swap candidates that are about to decohere. +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. +Rejects the swap candidates that are about to decohere by checking their time of creation, while the decoherence protocol, [`DecoherenceProt`](@ref) deletes such qubits independently. + +See also: [`SwapperKeeper`](@ref) + $TYPEDFIELDS """ @@ -486,8 +500,8 @@ end # and forward the message to that node. history = querydelete!(localslot, EntanglementHistory, pastremotenode, pastremoteslotid, # who we were entangled to (node, slot) - ❓, ❓, # who we swapped with (node, slot) - ❓) # which local slot used to be entangled with whom we swapped with + ❓, ❓, # who we swapped with (node, slot) + ❓) # which local slot used to be entangled with whom we swapped with if !isnothing(history) # @debug "tracker @$(prot.node) history: $(history) | msg: $msg" @@ -500,7 +514,7 @@ end else # We have a delete message but the qubit was swapped so add a tag and forward to swapped node @debug "EntanglementTracker @$(prot.node): history=`$(history)` | message=`$msg` | Sending to $(whoweswappedwith_node).$(whoweswappedwith_slotidx)" msghist = Tag(updatetagsymbol, pastremotenode, pastremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx) - tag!(localslot, updatetagsymbol, prot.node, localslot, whoweswappedwith_node, whoweswappedwith_slotidx) + tag!(localslot, updatetagsymbol, prot.node, localslot.idx, whoweswappedwith_node, whoweswappedwith_slotidx) put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) end continue @@ -561,7 +575,6 @@ end continue else query2 = query(prot.net[prot.nodeB], EntanglementCounterpart, prot.nodeA, query1.slot.idx; locked=false, assigned=true) - # don't really need to check `iscoherent` the second time, but just for safety if isnothing(query2) # in case EntanglementUpdate hasn't reached the second node yet, but the first node has the EntanglementCounterpart @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): query on second node found no entanglement (yet...)" @yield timeout(prot.sim, prot.period) @@ -592,7 +605,8 @@ end """ $TYPEDEF -A protocol running at a node, checking periodically for any decoherent entanglement and emptying such slots. +A protocol running at a node, checking periodically for any qubits in the node that have remained unused for more than the retention period of the +qubit and emptying such slots. $FIELDS """ @@ -619,6 +633,7 @@ end reg = prot.net[prot.node] while true for slot in reg + islocked(slot) && continue @yield lock(slot) info = query(slot, EntanglementCounterpart, ❓, ❓) if isnothing(info) unlock(slot);continue end diff --git a/src/messagebuffer.jl b/src/messagebuffer.jl index 6d5daee..40d24d2 100644 --- a/src/messagebuffer.jl +++ b/src/messagebuffer.jl @@ -21,7 +21,7 @@ function Base.put!(cf::ChannelForwarder, tag) tag = convert(Tag, tag) # shortest path calculated by Graphs.a_star nexthop = first(a_star(cf.net.graph, cf.src, cf.dst)) - # @debug "ChannelForwarder: Forwarding message from node $(nexthop.src) to node $(nexthop.dst) | message=$(tag)| end destination=$(cf.dst)" + @debug "ChannelForwarder: Forwarding message from node $(nexthop.src) to node $(nexthop.dst) | message=$(tag)| end destination=$(cf.dst)" put!(channel(cf.net, cf.src=>nexthop.dst; permit_forward=false), tag_types.Forward(tag, cf.dst)) end diff --git a/src/networks.jl b/src/networks.jl index fa402a6..a10dc36 100644 --- a/src/networks.jl +++ b/src/networks.jl @@ -14,7 +14,6 @@ struct RegisterNet end function RegisterNet(graph::SimpleGraph, registers, vertex_metadata, edge_metadata, directed_edge_metadata) - glcnt[] = 0 # set the global counter of `guid`s to zero whenever a new network is initialized 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) diff --git a/src/queries.jl b/src/queries.jl index 567decc..f7a3200 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -44,27 +44,6 @@ function untag!(ref::RegOrRegRef, id::Integer) return to_be_deleted end -#= # Should not exist. Rather, `querydelete!` should be used. -"""$TYPEDSIGNATURES - -Remove the unique tag matching the given query from a [`RegRef`](@ref) or a [`Register`](@ref). - -See also: [`query`](@ref), [`tag!`](@ref) -""" -function untag!(ref::RegOrRegRef, args...) - matches = queryall(ref, args...) - if length(matches) == 0 - throw(QueryError("Attempted to delete a tag matching a query, but no matching tag exists", untag!, args)) - elseif length(matches) > 1 - @show matches - @show length(matches) - throw(QueryError("Attempted to delete a tag matching a query, but there is no unique match to the query (consider manually using `queryall` and `untag!` instead)", untag!, args)) - end - id = matches[1].id - untag!(ref, id) -end -=# - """Wildcard type for use with the tag querying functionality. Usually you simply want an instance of this type (available as the constant [`W`](@ref) or [`❓`](@ref)). @@ -72,6 +51,7 @@ Usually you simply want an instance of this type (available as the constant [`W` See also: [`query`](@ref), [`tag!`](@ref)""" struct Wildcard end +const QueryTypes = Union{Function,Wildcard,TagElementTypes} """A wildcard instance for use with the tag querying functionality. @@ -93,7 +73,6 @@ $TYPEDSIGNATURES A query function that returns all slots of a register that have a given tag, with support for predicates and wildcards. - ```jldoctest; filter = r"id = (\\d*), " julia> r = Register(10); tag!(r[1], :symbol, 2, 3); @@ -112,8 +91,9 @@ julia> queryall(r, :symbol, ❓, >(5)) @NamedTuple{slot::RegRef, id::Int128, tag::Tag}[] ``` """ -queryall(args...; filo=true, kwargs...) = query(args..., Val{true}(); filo, kwargs...) -queryall(::MessageBuffer, args...; kwargs...) = throw(ArgumentError("`queryall` does not currently support `MessageBuffer`, chiefly to encourage the use of `querydelete!` instead")) +queryall(reg::RegOrRegRef, queryargs::Vararg{QueryTypes,N}; filo=true, kwargs...) where {N} = _query(reg, Val{true}(), Val{filo}(), queryargs...; kwargs...) +queryall(reg::RegOrRegRef, query::Tag; filo=true, kwargs...) = _query(reg, Val{true}(), Val{filo}(), query; kwargs...) +queryall(::MessageBuffer, queryargs...; kwargs...) = throw(ArgumentError("`queryall` does not currently support `MessageBuffer`, chiefly to encourage the use of `querydelete!` instead")) """ $TYPEDSIGNATURES @@ -163,31 +143,7 @@ julia> query(r, Int, 4, <(7)) (slot = Slot 5, id = 5, tag = TypeIntInt(Int64, 4, 5)::Tag) ``` -See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) -""" -function query(reg::Register, tag::Tag, ::Val{allB}=Val{false}(); locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true, ref=nothing) where {allB} - _query(reg, tag, Val{allB}(), Val{filo}(); locked=locked, assigned=assigned, ref=ref) -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, 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].slot] - if reg.tag_info[i].tag == 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].tag)) : return (slot=slot, id=i, tag=reg.tag_info[i].tag) - end - end - end - return allB ? result : nothing -end - - -""" -$TYPEDSIGNATURES - -A [`query`](@ref) on a single slot of a register. +A [`query`](@ref) can be on on a single slot of a register: ```jldoctest; filter = r"id = (\\d*), " julia> r = Register(5); @@ -204,23 +160,91 @@ julia> queryall(r[2], :symbol, 2, 3) 1-element Vector{@NamedTuple{slot::RegRef, id::Int128, tag::Tag}}: (slot = Slot 2, id = 6, tag = SymbolIntInt(:symbol, 2, 3)::Tag) ``` + +See also: [`queryall`](@ref), [`tag!`](@ref), [`W`](@ref), [`❓`](@ref) """ -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) +function query(reg::RegOrRegRef, queryargs::Vararg{QueryTypes,N}; locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) where {N} + _query(reg, Val{false}(), Val{filo}(), queryargs...; locked=locked, assigned=assigned) end - +query(reg::RegOrRegRef, query::Tag; locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing, filo::Bool=true) = _query(reg, Val{false}(), Val{filo}(), query; locked=locked, assigned=assigned) """ $TYPEDSIGNATURES You are advised to actually use [`querydelete!`](@ref), not `query` when working with classical message buffers. """ -function query(mb::MessageBuffer, tag::Tag, ::Val{allB}=Val{false}()) where {allB} - i = findfirst(t->t.tag==tag, mb.buffer) - return isnothing(i) ? nothing : (;depth=i, src=mb.buffer[i][1], tag=mb.buffer[i][2]) +function query(mb::MessageBuffer, queryargs::Vararg{QueryTypes,N}) where {N} + for (depth, (src, tag)) in pairs(mb.buffer) + query_good(tag, queryargs...) && return (;depth, src, tag) + end + return nothing +end + +for i in 1:10 # Vararg{Union{...}, N} does not specialize well, so we are explicitly making a method for each number of arguments + args = (:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l)[1:i] + query_expr = quote + function _query(reg::RegOrRegRef, ::Val{allB}, ::Val{filoB}, $(args...); + locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing + ) where {allB, filoB} # queryargs is so specifically typed in order to trigger the compiler heuristics for specialization, leading to very significant performance improvements + ref = isa(reg, RegRef) ? reg : nothing + reg = get_register(reg) + res = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] + l = length(reg.guids) + indices = filoB ? (l:-1:1) : (1:l) + for i in indices + i = reg.guids[i] + tag = reg.tag_info[i].tag + slot = reg[reg.tag_info[i].slot] + if _nothingor(ref, slot) && _nothingor(locked, islocked(slot)) && _nothingor(assigned, isassigned(slot)) + good = query_good(tag, $(args...)) + if good + allB ? push!(res, (slot=slot, id=i, tag=tag)) : return (slot=slot, id=i, tag=tag) + end + end + end + allB ? res : nothing + end + end + #println(query_expr) + eval(query_expr) end +for i in 1:10 + vars = (:a, :b, :c, :d, :e, :f, :g, :h, :i, :j, :k, :l) + VARS = (:A, :B, :C, :D, :E, :F, :G, :H, :I, :J, :K, :L) + args = vars[1:i] + checks = [:(query_check($(args[i]), $(VARS[i]))) for i in 1:i] + composite_check = reduce((l,r)->:($l && $r), checks) + cases = [] + for (symbol, variant) in pairs(Tag') + signature = methods(variant)[1].sig.parameters[2:end] + l = length(signature) + sigargs = VARS[1:l] + if l==i + push!(cases, :($symbol($(sigargs...)) => $composite_check)) + else + end + end + body_expr = isempty(cases) ? :(false) : quote + @cases tag begin + $(cases...) + _ => false + end + end + query_good_expr = quote + @inline function query_good(tag::Tag, $(args...)) + $body_expr + end + end + #println(query_good_expr) + eval(query_good_expr) +end +@inline _nothingor(l,r) = isnothing(l) || l==r +@inline query_check(q::T, t::T) where {T<:TagElementTypes} = (q==t)::Bool +@inline query_check(q::Function, t) = q(t)::Bool +@inline query_check(_::Wildcard, _) = true +@inline query_check(_, _) = false """ $TYPEDSIGNATURES @@ -297,12 +321,11 @@ t=1.0: query returns nothing t=3.0: query returns SymbolIntInt(:second_tag, 123, 456)::Tag received from node 3 ``` """ -function querydelete!(mb::MessageBuffer, args...;filo=true) +function querydelete!(mb::MessageBuffer, args...) r = query(mb, args...) return isnothing(r) ? nothing : popat!(mb.buffer, r.depth) end - """ $TYPEDSIGNATURES @@ -328,95 +351,35 @@ julia> queryall(reg, :tagA, ❓, ❓, ❓) ``` """ function querydelete!(reg::RegOrRegRef, args...; kwa...) - r = query(reg, args..., Val{false}(); kwa...) + r = query(reg, args...; kwa...) isnothing(r) || untag!(r.slot, r.id) return r end - -_nothingor(l,r) = isnothing(l) || l==r -_all() = true -_all(a::Bool) = a -_all(a::Bool, b::Bool) = a && b -_all(a::Bool, b::Bool, c::Bool) = a && b && c -_all(a::Bool, b::Bool, c::Bool, d::Bool) = a && b && c && d -_all(a::Bool, b::Bool, c::Bool, d::Bool, e::Bool) = a && b && c && d && e -_all(a::Bool, b::Bool, c::Bool, d::Bool, e::Bool, f::Bool) = a && b && c && d && e && f - -# Create a query function for each combination of tag arguments and/or wildcard arguments -for (tagsymbol, tagvariant) in pairs(tag_types) - sig = methods(tagvariant)[1].sig.parameters[2:end] - args = (:a, :b, :c, :d, :e, :f, :g)[1:length(sig)] - argssig = [:($a::$t) for (a,t) in zip(args, sig)] - - eval(quote function tag!(ref::RegRef, $(argssig...); kwa...) - tag!(ref, ($tagvariant)($(args...)); kwa...) - end end) - - eval(quote function Tag($(argssig...)) - ($tagvariant)($(args...)) - end end) - - eval(quote function query(tagcontainer, $(argssig...), ars...; kwa...) - query(tagcontainer, ($tagvariant)($(args...)), ars...; kwa...) - end end) - - int_idx_all = [i for (i,s) in enumerate(sig) if s == Int] - int_idx_combs = powerset(int_idx_all, 1) - for idx in int_idx_combs - complement_idx = tuple(setdiff(1:length(sig), idx)...) - sig_wild = collect(sig) - sig_wild[idx] .= Union{Wildcard,Function} - argssig_wild = [:($a::$t) for (a,t) in zip(args, sig_wild)] - 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, :id, :tag), Tuple{RegRef, Int128, Tag}}[] - op_guid = filo ? reverse : identity - for i in op_guid(reg.guids) - tag = reg.tag_info[i].tag - slot = reg[reg.tag_info[i].slot] - 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 - allB ? res : nothing - end end - newmethod_mb = quote function query(mb::MessageBuffer, $(argssig_wild...)) - for (depth, (src, tag)) in pairs(mb.buffer) - if isvariant(tag, ($(tagsymbol,))[1]) # a weird workaround for interpolating a symbol as a symbol - if _all($(nonwild_checks...)) && _all($(wild_checks...)) - return (;depth, src, tag) - end - end - end - end end - newmethod_rr = quote function query(ref::RegRef, $(argssig_wild...), ::Val{allB}=Val{false}(); filo::Bool=true) where {allB} - 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].tag - if isvariant(tag, ($(tagsymbol,))[1]) # a weird workaround for interpolating a symbol as a symbol - if _all($(nonwild_checks...)) && _all($(wild_checks...)) && (ref.reg[ref.reg.tag_info[i].slot] == ref) - allB ? push!(res, (slot=ref, id=i, tag=tag)) : return (slot=ref, id=i, tag=tag) - end - end - end - allB ? res : nothing - end end - #println(sig) - #println(sig_wild) - #println(newmethod_reg) - eval(newmethod_reg) - eval(newmethod_mb) # TODO there is a lot of code duplication here - eval(newmethod_rr) # TODO there is a lot of code duplication here +tag!(tagcontainer, args...) = tag!(tagcontainer, Tag(args...)) + +function _query(reg::RegOrRegRef, ::Val{allB}, ::Val{filoB}, query::Tag; locked::Union{Nothing,Bool}=nothing, assigned::Union{Nothing,Bool}=nothing) where {allB, filoB} + ref = isa(reg, RegRef) ? reg : nothing + reg = get_register(reg) + res = NamedTuple{(:slot, :id, :tag), Tuple{RegRef, Int128, Tag}}[] + l = length(reg.guids) + indices = filoB ? (l:-1:1) : (1:l) + for i in indices + i = reg.guids[i] + tag = reg.tag_info[i].tag + slot = reg[reg.tag_info[i].slot] + if _nothingor(ref, slot) && _nothingor(locked, islocked(slot)) && _nothingor(assigned, isassigned(slot)) && tag==query + allB ? push!(res, (slot=slot, id=i, tag=tag)) : return (slot=slot, id=i, tag=tag) + end end + allB ? res : nothing +end +function query(mb::MessageBuffer, query::Tag) + for (depth, (src, tag)) in pairs(mb.buffer) + tag==query && return (;depth, src, tag) + end + return nothing end - - """Find an empty unlocked slot in a given [`Register`](@ref). @@ -432,13 +395,14 @@ julia> findfreeslot(reg) |> isnothing true ``` """ -function findfreeslot(reg::Register; randomize=false) +function findfreeslot(reg::Register; randomize=false, margin=0) n_slots = length(reg.staterefs) - perm = randomize ? randperm : (x->1:x) - for i in perm(n_slots) - slot = reg[i] - if !islocked(slot) && !isassigned(slot) - return slot + freeslots = sum((!isassigned(reg[i]) for i in 1:n_slots)) + if freeslots >= margin + perm = randomize ? randperm : (x->1:x) + for i in perm(n_slots) + slot = reg[i] + islocked(slot) || isassigned(slot) || return slot end end end @@ -452,4 +416,4 @@ end function Base.isassigned(r::Register,i::Int) # TODO erase r.stateindices[i] != 0 # TODO this also usually means r.staterefs[i] !== nothing - choose one and make things consistent end -Base.isassigned(r::RegRef) = isassigned(r.reg, r.idx) +Base.isassigned(r::RegRef) = isassigned(r.reg, r.idx) \ No newline at end of file diff --git a/test/test_protocolzoo_entanglement_consumer.jl b/test/test_protocolzoo_entanglement_consumer.jl index e800446..f3f90ff 100644 --- a/test/test_protocolzoo_entanglement_consumer.jl +++ b/test/test_protocolzoo_entanglement_consumer.jl @@ -19,7 +19,7 @@ for n in 3:30 sim = get_time_tracker(net) for e in edges(net) - eprot = EntanglerProt(sim, net, e.src, e.dst; rounds=-1, randomize=true) + eprot = EntanglerProt(sim, net, e.src, e.dst; rounds=-1, randomize=true, margin=5, hardmargin=3) @process eprot() end diff --git a/test/test_protocolzoo_entanglement_tracker_grid.jl b/test/test_protocolzoo_entanglement_tracker_grid.jl index 1d51408..655604a 100644 --- a/test/test_protocolzoo_entanglement_tracker_grid.jl +++ b/test/test_protocolzoo_entanglement_tracker_grid.jl @@ -9,7 +9,7 @@ using Test if isinteractive() using Logging - logger = ConsoleLogger(Logging.Warn; meta_formatter=(args...)->(:black,"","")) + logger = ConsoleLogger(Logging.Debug; meta_formatter=(args...)->(:black,"","")) global_logger(logger) println("Logger set to debug") end From 39dbbfd9c67c02cb64f3e06f6d4baa1ce4d12e6a Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 11 Jun 2024 11:49:28 -0400 Subject: [PATCH 44/93] renamed example files --- test/test_examples.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_examples.jl b/test/test_examples.jl index 48e3d5c..a896f80 100644 --- a/test/test_examples.jl +++ b/test/test_examples.jl @@ -38,7 +38,7 @@ end @safetestset "repeatergrid" begin if get(ENV, "QUANTUMSAVORY_PLOT_TEST","")=="true" - include("../examples/repeatergrid/repeatergrid_async.jl") - include("../examples/repeatergrid/repeatergrid_sync.jl") + include("../examples/1a_async_interactive_visualization.jl") + include("../examples/repeatergrid/2a_sync_interactive_visualization.jl") end end \ No newline at end of file From 7eda00ed1d1effe22aeae45ecf32c67cdc89fa9f Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 12 Jun 2024 15:13:06 -0400 Subject: [PATCH 45/93] fix --- test/test_examples.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_examples.jl b/test/test_examples.jl index a896f80..bbd6ac0 100644 --- a/test/test_examples.jl +++ b/test/test_examples.jl @@ -38,7 +38,7 @@ end @safetestset "repeatergrid" begin if get(ENV, "QUANTUMSAVORY_PLOT_TEST","")=="true" - include("../examples/1a_async_interactive_visualization.jl") + include("../examples/repeatergrid/1a_async_interactive_visualization.jl") include("../examples/repeatergrid/2a_sync_interactive_visualization.jl") end end \ No newline at end of file From fa64154a18a79cd4c4ec2c9da269f4d93ad4f8c5 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 17 Jun 2024 15:37:42 -0400 Subject: [PATCH 46/93] More logic for delete-swap-swap case --- src/ProtocolZoo/ProtocolZoo.jl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 39ad9d5..817cbf6 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -521,7 +521,12 @@ end end if !isnothing(querydelete!(localslot, EntanglementDelete, prot.node, localslot.idx, pastremotenode, pastremoteslotid)) #deletion from both sides of the swap, deletion msg when both qubits of a pair are deleted, or when EU arrives after ED at swap node with two simultaneous swaps and deletion on one side - @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled" + if !(isnothing(updategate)) # EU message, hence to handle a possible delete-swap-swap case, we need to update the EntanglementDelete tag + tag!(localslot, EntanglementDelete, prot.node, localslot.idx, newremotenode, newremoteslotid) + @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled and EntanglementDelete tag updated" + else # when the message is EntanglementDelete and the slot also has an EntanglementDelete tag(both qubits were deleted), do nothing + @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled" + end continue end From 8c52609de31aecf1990954246d62d769bcbb8450 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 17 Jun 2024 16:36:51 -0400 Subject: [PATCH 47/93] typo in file name --- ...e_visualization.jl.jl => 2a_sync_interactive_visualization.jl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/repeatergrid/{2a_sync_interactive_visualization.jl.jl => 2a_sync_interactive_visualization.jl} (100%) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl similarity index 100% rename from examples/repeatergrid/2a_sync_interactive_visualization.jl.jl rename to examples/repeatergrid/2a_sync_interactive_visualization.jl From c591f6409295181026cfc473cdd7614f2fa819cf Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 17 Jun 2024 23:09:31 -0400 Subject: [PATCH 48/93] More work on requested changes --- CHANGELOG.md | 8 ++ src/ProtocolZoo/ProtocolZoo.jl | 252 +-------------------------------- src/ProtocolZoo/decoherence.jl | 60 ++++++++ src/ProtocolZoo/swapping.jl | 186 ++++++++++++++++++++++++ src/queries.jl | 19 ++- 5 files changed, 273 insertions(+), 252 deletions(-) create mode 100644 src/ProtocolZoo/decoherence.jl create mode 100644 src/ProtocolZoo/swapping.jl diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e1a9fa..9cca833 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # News +## v0.4.2 - 2024-00-00 + +- Develop `DecoherenceProt` to deal with deadlocks in a simulation +- Expand `SwapperProt` into `SwapperKeeper` and `SwapperShedder` to work with `DecoherenceProt` in asynchronous and synchronous mode +- Tutorial for entanglement distribution on a grid +- Interactive examples using `SwapperKeeper` and `SwapperShedder` for simulation and visualization +- WebGL demos for the two ways of doing swapping and decoherence. + ## v0.4.1 - 2024-06-05 - Significant improvements to the performance of `query`. diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 817cbf6..3da4941 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -1,7 +1,7 @@ module ProtocolZoo using QuantumSavory -import QuantumSavory: get_time_tracker, Tag, iscoherent +import QuantumSavory: get_time_tracker, Tag, isolderthan using QuantumSavory: Wildcard using QuantumSavory.CircuitZoo: EntanglementSwap, LocalEntanglementSwap @@ -240,193 +240,6 @@ end end end -function random_index(arr) - return rand(keys(arr)) -end - -""" -$TYPEDEF - -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the decoherence prtocol, [`DecoherenceProt`](@ref) is used, then communications about the -decoherence status of qubit would be done with asynchronous messaging through the [`EntanglementTracker`](@ref). Thus, `SwapperKeeper` keeps(considers) all the swap candidates -without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the decoherence protocol and forwarding the deletion messages -to the swapped nodes after the swap. - -See also: [`SwapperShedder`](@ref) - -$TYPEDFIELDS -""" -@kwdef struct SwapperKeeper{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 - """a network graph of registers""" - net::RegisterNet - """the vertex of the node where swapping is happening""" - node::Int - """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" - nodeL::NL = ❓ - """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" - nodeH::NH = ❓ - """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ - chooseL::CL = random_index - """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ - chooseH::CH = random_index - """fixed "busy time" duration immediately before starting entanglement generation attempts""" - local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in - """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" - retry_lock_time::LT = 0.1 - """how many rounds of this protocol to run (`-1` for infinite))""" - rounds::Int = -1 -end - -#TODO "convenience constructor for the missing things and finish this docstring" -function SwapperKeeper(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return SwapperKeeper(;sim, net, node, kwargs...) -end - -@resumable function (prot::SwapperKeeper)() - rounds = prot.rounds - round = 1 - while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) - if isnothing(qubit_pair) - isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO - @yield timeout(prot.sim, prot.retry_lock_time) - continue - end - - (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, 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, 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) - - uptotime!((q1, q2), now(prot.sim)) - swapcircuit = LocalEntanglementSwap() - xmeas, zmeas = swapcircuit(q1, q2) - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) - put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) - put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" - unlock(q1) - unlock(q2) - rounds==-1 || (rounds -= 1) - round += 1 - end -end - -function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false, buffer_time=nothing, retention_time=nothing) - reg = net[node] - low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot, buffer_time, retention_time, n.id)] - high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||iscoherent(n.slot, buffer_time, retention_time, n.id)] - - (isempty(low_nodes) || isempty(high_nodes)) && return nothing - il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property - ih = choose_high((n.tag[2] for n in high_nodes)) - return (low_nodes[il], high_nodes[ih]) -end - -""" -$TYPEDEF - -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. -Rejects the swap candidates that are about to decohere by checking their time of creation, while the decoherence protocol, [`DecoherenceProt`](@ref) deletes such qubits independently. - -See also: [`SwapperKeeper`](@ref) - - -$TYPEDFIELDS -""" -@kwdef struct SwapperShedder{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 - """a network graph of registers""" - net::RegisterNet - """the vertex of the node where swapping is happening""" - node::Int - """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" - nodeL::NL = ❓ - """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" - nodeH::NH = ❓ - """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ - chooseL::CL = random_index - """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ - chooseH::CH = random_index - """fixed "busy time" duration immediately before starting entanglement generation attempts""" - local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in - """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" - retry_lock_time::LT = 0.1 - """how many rounds of this protocol to run (`-1` for infinite))""" - rounds::Int = -1 - """what is the oldest a qubit should be to be picked for a swap""" - retention_time::Float64 = 5.0 - """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" - buffer_time::Float64 = 0.5 -end - - -#TODO "convenience constructor for the missing things and finish this docstring" -function SwapperShedder(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return SwapperShedder(;sim, net, node, kwargs...) -end - -@resumable function (prot::SwapperShedder)() - rounds = prot.rounds - round = 1 - while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=true, buffer_time=prot.buffer_time, retention_time=prot.retention_time) - if isnothing(qubit_pair) - isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO - @yield timeout(prot.sim, prot.retry_lock_time) - continue - end - - (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, 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, 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) - - uptotime!((q1, q2), now(prot.sim)) - swapcircuit = LocalEntanglementSwap() - xmeas, zmeas = swapcircuit(q1, q2) - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) - put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) - put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" - unlock(q1) - unlock(q2) - rounds==-1 || (rounds -= 1) - round += 1 - end -end - """ $TYPEDEF @@ -607,68 +420,9 @@ end end end -""" -$TYPEDEF - -A protocol running at a node, checking periodically for any qubits in the node that have remained unused for more than the retention period of the -qubit and emptying such slots. - -$FIELDS -""" -@kwdef struct DecoherenceProt <: AbstractProtocol - """time-and-schedule-tracking instance from `ConcurrentSim`""" - sim::Simulation - """a network graph of registers""" - net::RegisterNet - """the vertex index of node A""" - node::Int - """time period between successive queries on the node""" - period::Float64 = 0.1 - """Time after which a slot is emptied""" - retention_time::Float64 = 5.0 - """No messages are sent when this is set to true""" - sync::Bool = false -end - -function DecoherenceProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return DecoherenceProt(;sim, net, node, kwargs...) -end - -@resumable function (prot::DecoherenceProt)() - reg = prot.net[prot.node] - while true - for slot in reg - islocked(slot) && continue - @yield lock(slot) - info = query(slot, EntanglementCounterpart, ❓, ❓) - if isnothing(info) unlock(slot);continue end - if now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time - untag!(slot, info.id) - traceout!(slot) - msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) - tag!(slot, msg) - (prot.sync) || put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) - @debug "DecoherenceProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" - end - - #delete old history tags - info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) - if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time - untag!(slot, info.id) - end - - #delete old EntanglementDelete tags - info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) - if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time - untag!(slot, info.id) - end - unlock(slot) - end - @yield timeout(prot.sim, prot.period) - end -end - +include("decoherence.jl") +include("swapping.jl") include("switches.jl") using .Switches diff --git a/src/ProtocolZoo/decoherence.jl b/src/ProtocolZoo/decoherence.jl new file mode 100644 index 0000000..a133143 --- /dev/null +++ b/src/ProtocolZoo/decoherence.jl @@ -0,0 +1,60 @@ +""" +$TYPEDEF + +A protocol running at a node, checking periodically for any qubits in the node that have remained unused for more than the retention period of the +qubit and emptying such slots. + +$FIELDS +""" +@kwdef struct DecoherenceProt <: AbstractProtocol + """time-and-schedule-tracking instance from `ConcurrentSim`""" + sim::Simulation + """a network graph of registers""" + net::RegisterNet + """the vertex index of node A""" + node::Int + """time period between successive queries on the node""" + period::Float64 = 0.1 + """Time after which a slot is emptied""" + retention_time::Float64 = 5.0 + """No messages are sent when this is set to true""" + sync::Bool = false +end + +function DecoherenceProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return DecoherenceProt(;sim, net, node, kwargs...) +end + +@resumable function (prot::DecoherenceProt)() + reg = prot.net[prot.node] + while true + for slot in reg + islocked(slot) && continue + @yield lock(slot) + info = query(slot, EntanglementCounterpart, ❓, ❓) + if isnothing(info) unlock(slot);continue end + if now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + traceout!(slot) + msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) + tag!(slot, msg) + (prot.sync) || put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) + @debug "DecoherenceProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" + end + + #delete old history tags + info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + end + + #delete old EntanglementDelete tags + info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + untag!(slot, info.id) + end + unlock(slot) + end + @yield timeout(prot.sim, prot.period) + end +end \ No newline at end of file diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl new file mode 100644 index 0000000..f7865da --- /dev/null +++ b/src/ProtocolZoo/swapping.jl @@ -0,0 +1,186 @@ +function random_index(arr) + return rand(keys(arr)) +end + +""" +$TYPEDEF + +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the decoherence prtocol, [`DecoherenceProt`](@ref) is used, then communications about the +decoherence status of qubit would be done with asynchronous messaging through the [`EntanglementTracker`](@ref). Thus, `SwapperKeeper` keeps(considers) all the swap candidates +without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the decoherence protocol and forwarding the deletion messages +to the swapped nodes after the swap. + +See also: [`SwapperShedder`](@ref) + +$TYPEDFIELDS +""" +@kwdef struct SwapperKeeper{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 + """a network graph of registers""" + net::RegisterNet + """the vertex of the node where swapping is happening""" + node::Int + """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" + nodeL::NL = ❓ + """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" + nodeH::NH = ❓ + """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ + chooseL::CL = random_index + """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ + chooseH::CH = random_index + """fixed "busy time" duration immediately before starting entanglement generation attempts""" + local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in + """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" + retry_lock_time::LT = 0.1 + """how many rounds of this protocol to run (`-1` for infinite))""" + rounds::Int = -1 +end + +#TODO "convenience constructor for the missing things and finish this docstring" +function SwapperKeeper(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return SwapperKeeper(;sim, net, node, kwargs...) +end + +@resumable function (prot::SwapperKeeper)() + rounds = prot.rounds + round = 1 + while rounds != 0 + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) + if isnothing(qubit_pair) + isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO + @yield timeout(prot.sim, prot.retry_lock_time) + continue + end + + (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, 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, 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) + + uptotime!((q1, q2), now(prot.sim)) + swapcircuit = LocalEntanglementSwap() + xmeas, zmeas = swapcircuit(q1, q2) + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) + put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) + @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) + put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) + @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + unlock(q1) + unlock(q2) + rounds==-1 || (rounds -= 1) + round += 1 + end +end + +function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false, buffer_time=nothing, retention_time=nothing) + reg = net[node] + low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||!isolderthan(n.slot, retention_time-buffer_time)] + high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||!isolderthan(n.slot, retention_time-buffer_time)] + + (isempty(low_nodes) || isempty(high_nodes)) && return nothing + il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property + ih = choose_high((n.tag[2] for n in high_nodes)) + return (low_nodes[il], high_nodes[ih]) +end + +""" +$TYPEDEF + +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. +Rejects the swap candidates that are about to decohere by checking their time of creation, while the decoherence protocol, [`DecoherenceProt`](@ref) deletes such qubits independently. + +See also: [`SwapperKeeper`](@ref) + + +$TYPEDFIELDS +""" +@kwdef struct SwapperShedder{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 + """a network graph of registers""" + net::RegisterNet + """the vertex of the node where swapping is happening""" + node::Int + """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" + nodeL::NL = ❓ + """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" + nodeH::NH = ❓ + """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ + chooseL::CL = random_index + """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ + chooseH::CH = random_index + """fixed "busy time" duration immediately before starting entanglement generation attempts""" + local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in + """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" + retry_lock_time::LT = 0.1 + """how many rounds of this protocol to run (`-1` for infinite))""" + rounds::Int = -1 + """what is the oldest a qubit should be to be picked for a swap""" + retention_time::Float64 = 5.0 + """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" + buffer_time::Float64 = 0.5 +end + + +#TODO "convenience constructor for the missing things and finish this docstring" +function SwapperShedder(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return SwapperShedder(;sim, net, node, kwargs...) +end + +@resumable function (prot::SwapperShedder)() + rounds = prot.rounds + round = 1 + while rounds != 0 + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=true, buffer_time=prot.buffer_time, retention_time=prot.retention_time) + if isnothing(qubit_pair) + isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO + @yield timeout(prot.sim, prot.retry_lock_time) + continue + end + + (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, 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, 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) + + uptotime!((q1, q2), now(prot.sim)) + swapcircuit = LocalEntanglementSwap() + xmeas, zmeas = swapcircuit(q1, q2) + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) + put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) + @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + # send from here to new entanglement counterpart: + # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction + msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) + put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) + @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + unlock(q1) + unlock(q2) + rounds==-1 || (rounds -= 1) + round += 1 + end +end \ No newline at end of file diff --git a/src/queries.jl b/src/queries.jl index f7a3200..672d416 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -407,9 +407,22 @@ function findfreeslot(reg::Register; randomize=false, margin=0) end end -function iscoherent(slot::RegRef, buffer_time, retention_time, id) - if !isassigned(slot) throw("Slot must be assigned with a quantum state before checking coherence") end - return (now(get_time_tracker(slot))) + buffer_time - slot.reg.tag_info[id][3] < retention_time +struct NotAssignedError <: Exception + msg + f +end + +function Base.showerror(io::IO, err::NotAssignedError) + print(io, "NotAssignedError: ") + println(io, err.msg) + println("In function: $(err.f)") +end + +function isolderthan(slot::RegRef, time_left) + if !isassigned(slot) throw(NotAssignedError("Slot must be assigned with a quantum state before checking coherence.", isolderthan)) end + id = query(slot, QuantumSavory.ProtocolZoo.EntanglementCounterpart, ❓, ❓).id + slot_time = slot.reg.tag_info[id][3] + return (now(get_time_tracker(slot))) - slot_time > time_left end From 35736de54eb15e40ca9921ca831b15be0da463ae Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 18 Jun 2024 14:40:59 -0400 Subject: [PATCH 49/93] more fixes --- src/ProtocolZoo/swapping.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index f7865da..ed86db7 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -55,14 +55,14 @@ end (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 + untag!(q1, id1) + untag!(q2, id2) @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, 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, 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) From 948ec3c7006a6fc77833ec806dc911a567734f0b Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 18 Jun 2024 15:38:51 -0400 Subject: [PATCH 50/93] fix --- docs/make.jl | 4 ++-- src/ProtocolZoo/swapping.jl | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index b2a5483..a2c6a04 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,7 @@ using Documenter using DocumenterCitations using QuantumSavory -DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) +DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory), :(using QuantumSavory.ProtocolZoo); recursive=true) function main() bib = CitationBibliography(joinpath(@__DIR__,"src/references.bib"), style=:authoryear) @@ -18,7 +18,7 @@ function main() format = Documenter.HTML( assets=["assets/init.js"] ), - modules = [QuantumSavory], + modules = [QuantumSavory, QuantumSavory.ProtocolZoo], authors = "Stefan Krastanov", pages = [ "QuantumSavory.jl" => "index.md", diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index ed86db7..8873dd8 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -55,16 +55,18 @@ end (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 + untag!(q1, id1) untag!(q2, id2) - @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) # 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) # 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) + + @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) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() From df969cf60bf5e2e305cf3f7f5bebebcff4bb6090 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 18 Jun 2024 15:59:01 -0400 Subject: [PATCH 51/93] fix for docs --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index a2c6a04..2194bb7 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,7 @@ using Documenter using DocumenterCitations using QuantumSavory -DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory), :(using QuantumSavory.ProtocolZoo); recursive=true) +DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) function main() bib = CitationBibliography(joinpath(@__DIR__,"src/references.bib"), style=:authoryear) From 3c6f2012bd8b17614f57f1070bb91fdefcf13642 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 18 Jun 2024 16:46:34 -0400 Subject: [PATCH 52/93] docs fix? --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index 2194bb7..077e4bd 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -5,7 +5,7 @@ using Documenter using DocumenterCitations using QuantumSavory -DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) +DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory; using QuantumSavory.ProtocolZoo); recursive=true) function main() bib = CitationBibliography(joinpath(@__DIR__,"src/references.bib"), style=:authoryear) From be46b21061bf6a0bc88203aac686eef1f4c364fa Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 20 Jun 2024 09:37:48 -0400 Subject: [PATCH 53/93] fix --- docs/make.jl | 5 +++-- src/ProtocolZoo/swapping.jl | 10 +++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/make.jl b/docs/make.jl index 077e4bd..c40e133 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,8 +4,9 @@ push!(LOAD_PATH,"../src/") using Documenter using DocumenterCitations using QuantumSavory +using QuantumSavory.ProtocolZoo -DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory; using QuantumSavory.ProtocolZoo); recursive=true) +DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) function main() bib = CitationBibliography(joinpath(@__DIR__,"src/references.bib"), style=:authoryear) @@ -18,7 +19,7 @@ function main() format = Documenter.HTML( assets=["assets/init.js"] ), - modules = [QuantumSavory, QuantumSavory.ProtocolZoo], + modules = [QuantumSavory], authors = "Stefan Krastanov", pages = [ "QuantumSavory.jl" => "index.md", diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index 8873dd8..392ec46 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -56,18 +56,18 @@ end (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 - untag!(q1, id1) - untag!(q2, id2) + + @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, 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, 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) - @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) - uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() xmeas, zmeas = swapcircuit(q1, q2) From 6a1a66e9c80134eaacc49b4d8f55967f62588c8b Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 20 Jun 2024 13:21:09 -0400 Subject: [PATCH 54/93] change in naming convention --- CHANGELOG.md | 4 ++-- docs/src/howto/repeatergrid/repeatergrid.md | 19 +++++++++++++++++-- examples/repeatergrid/Project.toml | 13 +++++++++++++ examples/repeatergrid/setup.jl | 2 +- src/ProtocolZoo/ProtocolZoo.jl | 6 +++--- src/ProtocolZoo/{decoherence.jl => cutoff.jl} | 10 +++++----- src/ProtocolZoo/swapping.jl | 6 +++--- 7 files changed, 44 insertions(+), 16 deletions(-) rename src/ProtocolZoo/{decoherence.jl => cutoff.jl} (84%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 42b5f68..bbb1759 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,8 @@ ## v0.4.2 - dev -- Develop `DecoherenceProt` to deal with deadlocks in a simulation -- Expand `SwapperProt` into `SwapperKeeper` and `SwapperShedder` to work with `DecoherenceProt` in asynchronous and synchronous mode +- Develop `CutoffProt` to deal with deadlocks in a simulation +- Expand `SwapperProt` into `SwapperKeeper` and `SwapperShedder` to work with `CutoffProt` in asynchronous and synchronous mode - Tutorial for entanglement distribution on a grid - Interactive examples using `SwapperKeeper` and `SwapperShedder` for simulation and visualization - WebGL demos for the two ways of doing swapping and decoherence. diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 50d98a4..f36138b 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -19,7 +19,11 @@ This employs functionality from the `ProtocolZoo` module of QuantumSavory to run - [`SwapperKeeper`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. -- [`EntanglementTracker`](@ref) Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperProt` specifically). +- [`EntanglementTracker`](@ref): Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperKeeper` & `CutoffProt` specifically). + +- [`CutoffProt`](@ref): As the simulation progresses, the unused entangled pairs generated by `EntanglerProt` need to be discarded due to the loss of fidelity under noise as they might not be suitable for networking applications beyond a certain cutoff interval of time from their instantiation. The `CutoffProt` is instantiated with a `retention_time` parameter that discards such qubits in each node. + +- [`EntanglementConsumer`](@ref): This protocol runs between the end nodes and consumes the final entanglement generated as a result of all of the above protocols, which is supposed to represent the qubits being consumed in a networking application. All of the above protocols rely on the query and tagging functionality as described in the [Tagging and Querying](@ref tagging-and-querying) section. @@ -104,6 +108,17 @@ for v in vertices(net) tracker = EntanglementTracker(sim, net, v) @process tracker() end + +# Entanglement usage/consumption by the network end nodes + +consumer = EntanglementConsumer(sim, net, 1, n^2) +@process consumer() + +# decoherence protocol runs at each node to free up slots that haven't been used past the retention time +for v in vertices(net) + decprot = DecoherenceProt(sim, net, v) + @process decprot() +end ``` We set up the simulation to run with a 6x6 grid of nodes above. Here, each node has 8 qubit slots. @@ -144,7 +159,7 @@ end # Result ```@repl -include("../../../../examples/repeatergrid/repeatergrid_async.jl") # hide +include("../../../../examples/repeatergrid/1a_async_interactive_visualization.jl") # hide ``` ```@raw html diff --git a/examples/repeatergrid/Project.toml b/examples/repeatergrid/Project.toml index e69de29..2eb8c02 100644 --- a/examples/repeatergrid/Project.toml +++ b/examples/repeatergrid/Project.toml @@ -0,0 +1,13 @@ +[deps] +Bonito = "824d6782-a2ef-11e9-3a09-e5662e0c26f8" +ConcurrentSim = "6ed1e86c-fcaf-46a9-97e0-2b26a2cdb499" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" +Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" +NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a" +QuantumSavory = "2de2e421-972c-4cb5-a0c3-999c85908079" +ResumableFunctions = "c5292f4c-5179-55e1-98c5-05642aab7184" +Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" +WGLMakie = "276b4fcb-3e11-5398-bf8b-a0c2d153d008" + +[compat] +Bonito = "3.1" \ No newline at end of file diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl index 53c61f3..b038498 100644 --- a/examples/repeatergrid/setup.jl +++ b/examples/repeatergrid/setup.jl @@ -83,7 +83,7 @@ function prepare_simulation(;sync=false) # decoherence protocol runs at each node to free up slots that haven't been used past the retention time period_dec = Observable(0.1) for v in vertices(net) - decprot = DecoherenceProt(sim, net, v; sync=sync, period=period_dec[]) # TODO default and slider for retention_time + decprot = CutoffProt(sim, net, v; sync=sync, period=period_dec[]) # TODO default and slider for retention_time @process decprot() end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 3da4941..f89ebe3 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -16,7 +16,7 @@ import SumTypes export # protocols - EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, DecoherenceProt, + EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, CutoffProt, # tags EntanglementCounterpart, EntanglementHistory, EntanglementUpdateX, EntanglementUpdateZ, # from Switches @@ -124,7 +124,7 @@ Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, ta """ $TYPEDEF -This tag arrives as a message from a remote node's Decoherence Protocol to which the current node used to be entangled, to +This tag arrives as a message from a remote node's Cutoff Protocol to which the current node used to be entangled, to update the classical metadata of the entangled slot and empty it $TYPEDFIELDS @@ -421,7 +421,7 @@ end end -include("decoherence.jl") +include("cutoff.jl") include("swapping.jl") include("switches.jl") using .Switches diff --git a/src/ProtocolZoo/decoherence.jl b/src/ProtocolZoo/cutoff.jl similarity index 84% rename from src/ProtocolZoo/decoherence.jl rename to src/ProtocolZoo/cutoff.jl index a133143..c29af9f 100644 --- a/src/ProtocolZoo/decoherence.jl +++ b/src/ProtocolZoo/cutoff.jl @@ -6,7 +6,7 @@ qubit and emptying such slots. $FIELDS """ -@kwdef struct DecoherenceProt <: AbstractProtocol +@kwdef struct CutoffProt <: AbstractProtocol """time-and-schedule-tracking instance from `ConcurrentSim`""" sim::Simulation """a network graph of registers""" @@ -21,11 +21,11 @@ $FIELDS sync::Bool = false end -function DecoherenceProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return DecoherenceProt(;sim, net, node, kwargs...) +function CutoffProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return CutoffProt(;sim, net, node, kwargs...) end -@resumable function (prot::DecoherenceProt)() +@resumable function (prot::CutoffProt)() reg = prot.net[prot.node] while true for slot in reg @@ -39,7 +39,7 @@ end msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) tag!(slot, msg) (prot.sync) || put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) - @debug "DecoherenceProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" + @debug "CutoffProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" end #delete old history tags diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index 392ec46..dc6c326 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -5,9 +5,9 @@ end """ $TYPEDEF -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the decoherence prtocol, [`DecoherenceProt`](@ref) is used, then communications about the +A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the cutoff prtocol, [`CutoffProt`](@ref) is used, then communications about the decoherence status of qubit would be done with asynchronous messaging through the [`EntanglementTracker`](@ref). Thus, `SwapperKeeper` keeps(considers) all the swap candidates -without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the decoherence protocol and forwarding the deletion messages +without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the cutoff protocol and forwarding the deletion messages to the swapped nodes after the swap. See also: [`SwapperShedder`](@ref) @@ -103,7 +103,7 @@ end $TYPEDEF A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. -Rejects the swap candidates that are about to decohere by checking their time of creation, while the decoherence protocol, [`DecoherenceProt`](@ref) deletes such qubits independently. +Rejects the swap candidates that are about to go past their cutoff/retention time by checking their time of creation, while the cutoff protocol, [`CutoffProt`](@ref) deletes such qubits independently. See also: [`SwapperKeeper`](@ref) From aa8ded3965a5523f274c5e59f4ae52965789098e Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 22:27:47 -0400 Subject: [PATCH 55/93] a bit more inline comments for protocolzoo.jl --- src/ProtocolZoo/ProtocolZoo.jl | 46 ++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index f89ebe3..3341698 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -125,9 +125,11 @@ Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, ta $TYPEDEF This tag arrives as a message from a remote node's Cutoff Protocol to which the current node used to be entangled, to -update the classical metadata of the entangled slot and empty it +update the classical metadata of the entangled slot and empty it. $TYPEDFIELDS + +See also: [`CutoffProt`](@ref) """ @kwdef struct EntanglementDelete "The node that sent the deletion message" @@ -203,6 +205,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. \nGot:\n1. \t $a \n2.\t $b \n retrying..." @@ -264,13 +267,13 @@ 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, Z), (EntanglementUpdateZ, X), (EntanglementDelete, nothing)) - # look for EntanglementUpdate? past_remote_slot_idx local_slot_idx, new_remote_node, new_remote_slot_idx correction - if !isnothing(updategate) + for (updatetagsymbol, updategate) in ((EntanglementUpdateX, Z), (EntanglementUpdateZ, X), (EntanglementDelete, nothing)) # TODO this is getting ugly. Refactor EntanglementUpdateX and EntanglementUpdateZ to be the same parameterized tag + # look for EntanglementUpdate? or EntanglementDelete message sent to us + if !isnothing(updategate) # EntanglementUpdate msg = querydelete!(mb, updatetagsymbol, ❓, ❓, ❓, ❓, ❓, ❓) isnothing(msg) && continue (src, (_, pastremotenode, pastremoteslotid, localslotid, newremotenode, newremoteslotid, correction)) = msg - else + else # EntanglementDelete msg = querydelete!(mb, updatetagsymbol, ❓, ❓, ❓, ❓) isnothing(msg) && continue (src, (_, pastremotenode, pastremoteslotid, _, localslotid)) = msg @@ -281,7 +284,7 @@ end localslot = nodereg[localslotid] # Check if the local slot is still present and believed to be entangled. - # We will need to perform a correction operation due to the swap, + # We will need to perform a correction operation due to the swap or a deletion due to the qubit being thrown out, # but there will be no message forwarding necessary. counterpart = querydelete!(localslot, EntanglementCounterpart, pastremotenode, pastremoteslotid) if !isnothing(counterpart) @@ -293,9 +296,9 @@ end time_before_lock != time_after_lock && @debug "EntanglementTracker @$(prot.node): Needed Δt=$(time_after_lock-time_before_lock) to get a lock" if !isassigned(localslot) 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.") + 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.") # TODO make it configurable whether an error is thrown and plug it into the logging module end - if !isnothing(updategate) #EntanglementUpdate + if !isnothing(updategate) # EntanglementUpdate # Pauli frame correction gate if correction==2 apply!(localslot, updategate) @@ -309,22 +312,22 @@ end continue end - # If not, check if we have a record of the entanglement being swapped to a different remote node, + # If there is nothing still stored locally, check if we have a record of the entanglement being swapped to a different remote node, # and forward the message to that node. history = querydelete!(localslot, EntanglementHistory, pastremotenode, pastremoteslotid, # who we were entangled to (node, slot) - ❓, ❓, # who we swapped with (node, slot) - ❓) # which local slot used to be entangled with whom we swapped with + ❓, ❓, # who we swapped with (node, slot) + ❓) # 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.tag - if !isnothing(updategate) + if !isnothing(updategate) # EntanglementUpdate + # Forward the update tag to the swapped node and store a new history tag so that we can forward the next update tag to the new node 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) put!(channel(prot.net, prot.node=>whoweswappedwith_node; permit_forward=true), msghist) - else # We have a delete message but the qubit was swapped so add a tag and forward to swapped node + else # EntanglementDelete + # We have a delete message but the qubit was swapped so add a tag and forward to swapped node @debug "EntanglementTracker @$(prot.node): history=`$(history)` | message=`$msg` | Sending to $(whoweswappedwith_node).$(whoweswappedwith_slotidx)" msghist = Tag(updatetagsymbol, pastremotenode, pastremoteslotid, whoweswappedwith_node, whoweswappedwith_slotidx) tag!(localslot, updatetagsymbol, prot.node, localslot.idx, whoweswappedwith_node, whoweswappedwith_slotidx) @@ -333,12 +336,17 @@ end continue end + # Finally, if there the history of a swap is not present in the log anymore, + # it must be because a delete message was received, and forwarded, + # and the swap history was deleted, and replaced with a delete history. if !isnothing(querydelete!(localslot, EntanglementDelete, prot.node, localslot.idx, pastremotenode, pastremoteslotid)) #deletion from both sides of the swap, deletion msg when both qubits of a pair are deleted, or when EU arrives after ED at swap node with two simultaneous swaps and deletion on one side - if !(isnothing(updategate)) # EU message, hence to handle a possible delete-swap-swap case, we need to update the EntanglementDelete tag + if !(isnothing(updategate)) # EntanglementUpdate + # to handle a possible delete-swap-swap case, we need to update the EntanglementDelete tag tag!(localslot, EntanglementDelete, prot.node, localslot.idx, newremotenode, newremoteslotid) @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled and EntanglementDelete tag updated" - else # when the message is EntanglementDelete and the slot also has an EntanglementDelete tag(both qubits were deleted), do nothing - @debug "EntanglementTracker @$(prot.node): message=`$msg` for deleted qubit handled" + else # EntanglementDelete + # when the message is EntanglementDelete and the slot history also has an EntanglementDelete tag (both qubits were deleted), do nothing + @debug "EntanglementTracker @$(prot.node): message=`$msg` is for a deleted qubit and is thus dropped" end continue end @@ -407,7 +415,7 @@ end @debug "EntanglementConsumer between $(prot.nodeA) and $(prot.nodeB): queries successful, consuming entanglement between .$(q1.idx) and .$(q2.idx) @ $(now(prot.sim))" 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 Swapper + # TODO do we need to add EntanglementHistory or EntanglementDelete and should that be a different EntanglementHistory since the current one is specifically for Swapper # 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)) ob2 = real(observable((q1, q2), X⊗X)) From 9cda39c80e8b9634b52f1e46b00da416e173bc57 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 23:03:59 -0400 Subject: [PATCH 56/93] simplify SwapperProt --- docs/src/howto/repeatergrid/repeatergrid.md | 6 +- .../firstgenrepeater_v2/2_swapper_example.jl | 2 +- examples/firstgenrepeater_v2/setup.jl | 2 +- .../1a_async_interactive_visualization.jl | 2 +- .../1b_async_wglmakie_interactive.jl | 6 +- .../2a_sync_interactive_visualization.jl | 2 +- .../2b_sync_wglmakie_interactive.jl | 4 +- examples/repeatergrid/setup.jl | 11 +- src/ProtocolZoo/ProtocolZoo.jl | 2 +- src/ProtocolZoo/swapping.jl | 127 ++++-------------- src/ProtocolZoo/switches.jl | 2 +- .../test_protocolzoo_entanglement_consumer.jl | 4 +- test/test_protocolzoo_entanglement_tracker.jl | 6 +- ...t_protocolzoo_entanglement_tracker_grid.jl | 6 +- 14 files changed, 53 insertions(+), 129 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index f36138b..55901fe 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -17,9 +17,9 @@ This employs functionality from the `ProtocolZoo` module of QuantumSavory to run - [`EntanglerProt`](@ref): Entangler protocol to produce link level entanglement at each edge in the network -- [`SwapperKeeper`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. +- [`SwapperProt`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. -- [`EntanglementTracker`](@ref): Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperKeeper` & `CutoffProt` specifically). +- [`EntanglementTracker`](@ref): Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperProt` & `CutoffProt` specifically). - [`CutoffProt`](@ref): As the simulation progresses, the unused entangled pairs generated by `EntanglerProt` need to be discarded due to the loss of fidelity under noise as they might not be suitable for networking applications beyond a certain cutoff interval of time from their instantiation. The `CutoffProt` is instantiated with a `retention_time` parameter that discards such qubits in each node. @@ -100,7 +100,7 @@ for i in 2:(n^2 - 1) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) @process swapper() end diff --git a/examples/firstgenrepeater_v2/2_swapper_example.jl b/examples/firstgenrepeater_v2/2_swapper_example.jl index 12d122b..6d8d95d 100644 --- a/examples/firstgenrepeater_v2/2_swapper_example.jl +++ b/examples/firstgenrepeater_v2/2_swapper_example.jl @@ -20,7 +20,7 @@ for (;src, dst) in edges(network) @process eprot() end for node in vertices(network) - sprot = SwapperKeeper(sim, network, node; nodeL = <(node), nodeH = >(node), chooseL = argmin, chooseH = argmax) + sprot = SwapperProt(sim, network, node; nodeL = <(node), nodeH = >(node), chooseL = argmin, chooseH = argmax) @process sprot() end diff --git a/examples/firstgenrepeater_v2/setup.jl b/examples/firstgenrepeater_v2/setup.jl index d0703c2..edc69ae 100644 --- a/examples/firstgenrepeater_v2/setup.jl +++ b/examples/firstgenrepeater_v2/setup.jl @@ -14,7 +14,7 @@ using QuantumSavory # Predefined useful circuits using QuantumSavory.CircuitZoo: EntanglementSwap, Purify2to1 -using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperKeeper +using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperProt ## # Create a handful of qubit registers in a chain diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index ad9fd3e..9face67 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -33,7 +33,7 @@ sg = SliderGrid( range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), - (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl index 540d475..a20f877 100644 --- a/examples/repeatergrid/1b_async_wglmakie_interactive.jl +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -40,7 +40,7 @@ function prepare_singlerun() range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), - (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), @@ -114,8 +114,8 @@ landing = Bonito.App() do Both of these are presented in the top and bottom graphs on the right above respectively. All the classical information about the entanglement status of nodes after swaps or deletions(decoherence protocols) is communicated through - asynchronous messaging with the help of tags and queries and handled by the entanglement tracker. With this the swapper protocol(`SwapperKeeper`) - considers all the proposed candidates for a swap, relying on the messages sent by the decoherence protocol to the entanglement tracker to delete any qubits that might have taken part + asynchronous messaging with the help of tags and queries and handled by the entanglement tracker. With this the swapper protocol(`SwapperProt`) + considers all the proposed candidates for a swap, relying on the messages sent by the decoherence protocol to the entanglement tracker to delete any qubits that might have taken part in a swap, while their entangled pair got deleted due to decoherence. If this happens all the qubits involved in the swap need to be discarded by forwarding the deletion message to the respective nodes. diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index 966920b..54b4747 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -33,7 +33,7 @@ sg = SliderGrid( range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), - (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl index aabaf64..fcfbaa6 100644 --- a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -40,7 +40,7 @@ function prepare_singlerun() range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", range=0.1:0.1:10.0, format="{:.2f}", startvalue=5.0), - (label="Time before a qubit's retention time runs out(for `SwapperShedder`)", + (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), @@ -115,7 +115,7 @@ landing = Bonito.App() do All the classical information about the entanglement status of nodes after swaps is communicated through asynchronous messaging with the help of tags and queries and handled by the entanglement tracker. The decoherence protocol doesn't generate - any messages here. Hence, the swapper protocol (SwapperShedder) checks every proposed candidate to be coherent before its used. Thus the swapper and decoherence protocol + any messages here. Hence, the swapper protocol (`SwapperProt` with `agelimit`) checks every proposed candidate to be coherent before its used. Thus the swapper and decoherence protocol interact in a synchronous manner here. [See and modify the code for this simulation on github.](https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/repeatergrid/2b_sync_wglmakie_interactive.jl) diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl index b038498..da21d8b 100644 --- a/examples/repeatergrid/setup.jl +++ b/examples/repeatergrid/setup.jl @@ -64,8 +64,13 @@ function prepare_simulation(;sync=false) h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = if sync SwapperShedder(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, local_busy_time=local_busy_time[], retry_lock_time=retry_lock_time[], retention_time=retention_time[], buffer_time=buffer_time[]) - else SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1, local_busy_time=local_busy_time[], retry_lock_time=retry_lock_time[]) end + swapper = SwapperProt( + sim, net, i; + nodeL = l, nodeH = h, + chooseL = cL, chooseH = cH, + rounds=-1, local_busy_time=local_busy_time[], + retry_lock_time=retry_lock_time[], + agelimit=sync ? retention_time[]-buffer_time[] : nothing) @process swapper() end @@ -88,4 +93,4 @@ function prepare_simulation(;sync=false) end return sim, net, graph, consumer, succ_prob, local_busy_time, retry_lock_time, retention_time, buffer_time, period_cons, period_dec -end \ No newline at end of file +end diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 3341698..a5dc5d5 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -16,7 +16,7 @@ import SumTypes export # protocols - EntanglerProt, SwapperKeeper, SwapperShedder, EntanglementTracker, EntanglementConsumer, CutoffProt, + EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer, CutoffProt, # tags EntanglementCounterpart, EntanglementHistory, EntanglementUpdateX, EntanglementUpdateZ, # from Switches diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index dc6c326..f755d1b 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -2,96 +2,17 @@ function random_index(arr) return rand(keys(arr)) end -""" -$TYPEDEF - -A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. If the cutoff prtocol, [`CutoffProt`](@ref) is used, then communications about the -decoherence status of qubit would be done with asynchronous messaging through the [`EntanglementTracker`](@ref). Thus, `SwapperKeeper` keeps(considers) all the swap candidates -without verifying their decoherence status, leaving it to the [`EntanglementTracker`](@ref) to handle deletions performed by the cutoff protocol and forwarding the deletion messages -to the swapped nodes after the swap. - -See also: [`SwapperShedder`](@ref) - -$TYPEDFIELDS -""" -@kwdef struct SwapperKeeper{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 - """a network graph of registers""" - net::RegisterNet - """the vertex of the node where swapping is happening""" - node::Int - """the vertex of one of the remote nodes for the swap, arbitrarily referred to as the "low" node (or a predicate function or a wildcard); if you are working on a repeater chain, a good choice is `<(current_node)`, i.e. any node to the "left" of the current node""" - nodeL::NL = ❓ - """the vertex of the other remote node for the swap, the "high" counterpart of `nodeL`; if you are working on a repeater chain, a good choice is `>(current_node)`, i.e. any node to the "right" of the current node""" - nodeH::NH = ❓ - """the `nodeL` predicate can return many positive candidates; `chooseL` picks one of them (by index into the array of filtered `nodeL` results), defaults to a random pick `arr->rand(keys(arr))`; if you are working on a repeater chain a good choice is `argmin`, i.e. the node furthest to the "left" """ - chooseL::CL = random_index - """the `nodeH` counterpart for `chooseH`; if you are working on a repeater chain a good choice is `argmax`, i.e. the node furthest to the "right" """ - chooseH::CH = random_index - """fixed "busy time" duration immediately before starting entanglement generation attempts""" - local_busy_time::Float64 = 0.0 # TODO the gates should have that busy time built in - """how long to wait before retrying to lock qubits if no qubits are available (`nothing` for queuing up and waiting)""" - retry_lock_time::LT = 0.1 - """how many rounds of this protocol to run (`-1` for infinite))""" - rounds::Int = -1 -end - -#TODO "convenience constructor for the missing things and finish this docstring" -function SwapperKeeper(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return SwapperKeeper(;sim, net, node, kwargs...) -end - -@resumable function (prot::SwapperKeeper)() - rounds = prot.rounds - round = 1 - while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH) - if isnothing(qubit_pair) - isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO - @yield timeout(prot.sim, prot.retry_lock_time) - continue - end - - (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, 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, 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) - - uptotime!((q1, q2), now(prot.sim)) - swapcircuit = LocalEntanglementSwap() - xmeas, zmeas = swapcircuit(q1, q2) - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) - put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" - # send from here to new entanglement counterpart: - # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction - msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) - put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperKeeper @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" - unlock(q1) - unlock(q2) - rounds==-1 || (rounds -= 1) - round += 1 - end -end - -function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; sync=false, buffer_time=nothing, retention_time=nothing) +function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_high; agelimit=nothing) reg = net[node] - low_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) if !(sync)||!isolderthan(n.slot, retention_time-buffer_time)] - high_nodes = [n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) if !(sync)||!isolderthan(n.slot, retention_time-buffer_time)] + low_nodes = [ + n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) + if isnothing(agelimit) || !isolderthan(n.slot, agelimit) + ] + high_nodes = [ + n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) + if isnothing(agelimit) || !isolderthan(n.slot, agelimit) + ] (isempty(low_nodes) || isempty(high_nodes)) && return nothing il = choose_low((n.tag[2] for n in low_nodes)) # TODO make [2] into a nice named property @@ -99,18 +20,19 @@ function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_h return (low_nodes[il], high_nodes[ih]) end + """ $TYPEDEF A protocol, running at a given node, that finds swappable entangled pairs and performs the swap. -Rejects the swap candidates that are about to go past their cutoff/retention time by checking their time of creation, while the cutoff protocol, [`CutoffProt`](@ref) deletes such qubits independently. - -See also: [`SwapperKeeper`](@ref) +Consider setting an `agelimit` on qubits +and using it together with the cutoff protocol, [`CutoffProt`](@ref), +which deletes qubits that are about to go past their cutoff/retention time. $TYPEDFIELDS """ -@kwdef struct SwapperShedder{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}} +@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 """a network graph of registers""" @@ -131,23 +53,20 @@ $TYPEDFIELDS retry_lock_time::LT = 0.1 """how many rounds of this protocol to run (`-1` for infinite))""" rounds::Int = -1 - """what is the oldest a qubit should be to be picked for a swap""" - retention_time::Float64 = 5.0 - """padding time so that we don't cross the `retention_time` while the asynchronous messaging takes place""" - buffer_time::Float64 = 0.5 + """what is the oldest a qubit should be to be picked for a swap (to avoid swapping with qubits that are about to be deleted, the agelimit should be shorter than the retention time of the cutoff protocol) (`nothing` for no limit) -- you probably want to use [`CutoffProt`](@ref) if you have an agelimit""" + agelimit::Union{Float64,Nothing} = nothing end - #TODO "convenience constructor for the missing things and finish this docstring" -function SwapperShedder(sim::Simulation, net::RegisterNet, node::Int; kwargs...) - return SwapperShedder(;sim, net, node, kwargs...) +function SwapperProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) + return SwapperProt(;sim, net, node, kwargs...) end -@resumable function (prot::SwapperShedder)() +@resumable function (prot::SwapperProt)() rounds = prot.rounds round = 1 while rounds != 0 - qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; sync=true, buffer_time=prot.buffer_time, retention_time=prot.retention_time) + qubit_pair = findswapablequbits(prot.net, prot.node, prot.nodeL, prot.nodeH, prot.chooseL, prot.chooseH; agelimit=prot.agelimit) if isnothing(qubit_pair) isnothing(prot.retry_lock_time) && error("We do not yet support waiting on register to make qubits available") # TODO @yield timeout(prot.sim, prot.retry_lock_time) @@ -174,15 +93,15 @@ end # tag with EntanglementUpdateX past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg1 = Tag(EntanglementUpdateX, prot.node, q1.idx, tag1[3], tag2[2], tag2[3], xmeas) put!(channel(prot.net, prot.node=>tag1[2]; permit_forward=true), msg1) - @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag1[2]) | message=`$msg1` | time = $(now(prot.sim))" # send from here to new entanglement counterpart: # tag with EntanglementUpdateZ past_local_node, past_local_slot_idx past_remote_slot_idx new_remote_node, new_remote_slot, correction msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) - @debug "SwapperShedder @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" unlock(q1) unlock(q2) rounds==-1 || (rounds -= 1) round += 1 end -end \ No newline at end of file +end diff --git a/src/ProtocolZoo/switches.jl b/src/ProtocolZoo/switches.jl index b03fdd5..05fb3e8 100644 --- a/src/ProtocolZoo/switches.jl +++ b/src/ProtocolZoo/switches.jl @@ -312,7 +312,7 @@ perform swaps to connect them and decrement the backlog counter. function _switch_run_swaps(prot, match) @debug "Switch $(prot.switchnode) performs swaps for client pairs $([(prot.clientnodes[i], prot.clientnodes[j]) for (i,j) in match])" for (i,j) in match - swapper = SwapperKeeper( # TODO be more careful about how much simulated time this takes + swapper = SwapperProt( # TODO be more careful about how much simulated time this takes sim=prot.sim, net=prot.net, node=prot.switchnode, nodeL=prot.clientnodes[i], nodeH=prot.clientnodes[j], rounds=1 diff --git a/test/test_protocolzoo_entanglement_consumer.jl b/test/test_protocolzoo_entanglement_consumer.jl index f3f90ff..52bbfb2 100644 --- a/test/test_protocolzoo_entanglement_consumer.jl +++ b/test/test_protocolzoo_entanglement_consumer.jl @@ -1,5 +1,5 @@ using QuantumSavory -using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperKeeper, EntanglementTracker, EntanglementConsumer +using QuantumSavory.ProtocolZoo: EntanglerProt, SwapperProt, EntanglementTracker, EntanglementConsumer using Graphs using ConcurrentSim using Test @@ -24,7 +24,7 @@ for n in 3:30 end for v in 2:n-1 - sprot = SwapperKeeper(sim, net, v; nodeL = <(v), nodeH = >(v), chooseL = argmin, chooseH = argmax, rounds = -1) + sprot = SwapperProt(sim, net, v; nodeL = <(v), nodeH = >(v), chooseL = argmin, chooseH = argmax, rounds = -1) @process sprot() end diff --git a/test/test_protocolzoo_entanglement_tracker.jl b/test/test_protocolzoo_entanglement_tracker.jl index ad19c01..6656d35 100644 --- a/test/test_protocolzoo_entanglement_tracker.jl +++ b/test/test_protocolzoo_entanglement_tracker.jl @@ -45,8 +45,8 @@ for i in 1:10 @test [islocked(ref) for i in vertices(net) for ref in net[i]] |> any == false - swapper2 = SwapperKeeper(sim, net, 2; nodeL = <(2), nodeH = >(2), chooseL = argmin, chooseH = argmax, rounds = 1) - swapper3 = SwapperKeeper(sim, net, 3; nodeL = <(3), nodeH = >(3), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper2 = SwapperProt(sim, net, 2; nodeL = <(2), nodeH = >(2), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper3 = SwapperProt(sim, net, 3; nodeL = <(3), nodeH = >(3), chooseL = argmin, chooseH = argmax, rounds = 1) @process swapper2() @process swapper3() run(sim, 80) @@ -100,7 +100,7 @@ for i in 1:30, n in 2:30 @process eprot() end for j in 2:n-1 - swapper = SwapperKeeper(sim, net, j; nodeL = <(j), nodeH = >(j), chooseL = argmin, chooseH = argmax, rounds = 1) + swapper = SwapperProt(sim, net, j; nodeL = <(j), nodeH = >(j), chooseL = argmin, chooseH = argmax, rounds = 1) @process swapper() end run(sim, 200) diff --git a/test/test_protocolzoo_entanglement_tracker_grid.jl b/test/test_protocolzoo_entanglement_tracker_grid.jl index 655604a..5186558 100644 --- a/test/test_protocolzoo_entanglement_tracker_grid.jl +++ b/test/test_protocolzoo_entanglement_tracker_grid.jl @@ -109,7 +109,7 @@ for path in paths h = x->check_nodes(net, path[i], x; low=false) cL = arr->choose_node(net, path[i], arr) cH = arr->choose_node(net, path[i], arr; low=false) - swapper = SwapperKeeper(sim, net, path[i]; nodeL=l, nodeH=h, chooseL=cL, chooseH=cH, rounds=1) + swapper = SwapperProt(sim, net, path[i]; nodeL=l, nodeH=h, chooseL=cL, chooseH=cH, rounds=1) @process swapper() end run(sim, 200) @@ -163,7 +163,7 @@ for n in 4:10 h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high @process swapper() end @@ -202,7 +202,7 @@ for n in 4:10 h(x) = check_nodes(net, i, x; low=false) cL(arr) = choose_node(net, i, arr) cH(arr) = choose_node(net, i, arr; low=false) - swapper = SwapperKeeper(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds = 5) # A single round doesn't always get the ends entangled, when number of nodes is high @process swapper() end From 2f205b722403f132c2c0244b04b463d048e64ca9 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 23:06:16 -0400 Subject: [PATCH 57/93] undo spurious whitespace changes to make the git history easier to skim --- test/test_protocolzoo_entanglement_consumer.jl | 1 - test/test_tags_and_queries.jl | 2 -- 2 files changed, 3 deletions(-) diff --git a/test/test_protocolzoo_entanglement_consumer.jl b/test/test_protocolzoo_entanglement_consumer.jl index 52bbfb2..4f34236 100644 --- a/test/test_protocolzoo_entanglement_consumer.jl +++ b/test/test_protocolzoo_entanglement_consumer.jl @@ -12,7 +12,6 @@ if isinteractive() end - for n in 3:30 regsize = 10 net = RegisterNet([Register(regsize) for j in 1:n]) diff --git a/test/test_tags_and_queries.jl b/test/test_tags_and_queries.jl index e7d2982..4d64d8c 100644 --- a/test/test_tags_and_queries.jl +++ b/test/test_tags_and_queries.jl @@ -21,7 +21,6 @@ tag!(r[3], :symbol1, 4, 1) tag!(r[5], Int, 4, 5) @test Tag(:symbol1, 2, 3) == 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 @@ -61,7 +60,6 @@ tag!(reg[3], EntanglementCounterpart, 2, 23) tag!(reg[3], EntanglementCounterpart, 1, 10) @test query(reg[3], EntanglementCounterpart, 1, 11) === nothing - @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; filo=false)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,1,10)) @test strip_id(query(reg[3], EntanglementCounterpart, 1, 10; filo=true)) == (slot = reg[3], tag = Tag(EntanglementCounterpart,1,10)) From 63b5bff51071e58af7fe5331ea050fd813881ebb Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 23:18:04 -0400 Subject: [PATCH 58/93] undo deleted plot (for now, to delete again if tests still fail) --- docs/src/visualizations.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index 40e0360..74be69b 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -65,6 +65,12 @@ fig And here with some extra tag metadata. +```@example vis +tag!(net[2,3], :specialplace, 1, 2) +tag!(net[2,3], :otherdata, 3, 4) +QuantumSavory.showmetadata(fig,ax,plt,2,3) +fig +``` ## The state of locks and various metadata in the network From de5cf6e81e5386265067dfb9e4f1e73fcb566a9d Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 23:35:24 -0400 Subject: [PATCH 59/93] cutoff protocol comment updates and type parameterization --- src/ProtocolZoo/ProtocolZoo.jl | 2 +- src/ProtocolZoo/cutoff.jl | 32 ++++++++++++++++++++------------ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index a5dc5d5..64233b9 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -351,7 +351,7 @@ end 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` or `EntanglementDelete` tags). This is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.") + 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` or `EntanglementDelete` tags). This might have happened due to `CutoffProt` deleting qubits while swaps are happening. Make sure that the retentian times in `CutoffProt` are sufficiently larger than the `agelimit` in `SwapperProt`. Otherwise is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.") end end @debug "EntanglementTracker @$(prot.node): Starting message wait at $(now(prot.sim)) with MessageBuffer containing: $(mb.buffer)" diff --git a/src/ProtocolZoo/cutoff.jl b/src/ProtocolZoo/cutoff.jl index c29af9f..41ae080 100644 --- a/src/ProtocolZoo/cutoff.jl +++ b/src/ProtocolZoo/cutoff.jl @@ -1,20 +1,22 @@ """ $TYPEDEF -A protocol running at a node, checking periodically for any qubits in the node that have remained unused for more than the retention period of the -qubit and emptying such slots. +A protocol running at a node, +checking periodically for any qubits in the node that +have remained unused for more than the retention period of the qubit +and emptying such slots. $FIELDS """ -@kwdef struct CutoffProt <: AbstractProtocol +@kwdef struct CutoffProt{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} """time-and-schedule-tracking instance from `ConcurrentSim`""" sim::Simulation """a network graph of registers""" net::RegisterNet - """the vertex index of node A""" + """the vertex index of the node on which the protocol is running""" node::Int - """time period between successive queries on the node""" - period::Float64 = 0.1 + """time period between successive queries on the node (`nothing` for queuing up)""" + period::LT = 0.1 """Time after which a slot is emptied""" retention_time::Float64 = 5.0 """No messages are sent when this is set to true""" @@ -26,14 +28,20 @@ function CutoffProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) end @resumable function (prot::CutoffProt)() + if isnothing(prot.period) + error("In `CutoffProt` we do not yet support quing up and waiting on register") # TODO + end reg = prot.net[prot.node] while true - for slot in reg + for slot in reg # TODO these should be done in parallel, otherwise we will be waiting on each slot, greatly slowing down the cutoffs islocked(slot) && continue @yield lock(slot) info = query(slot, EntanglementCounterpart, ❓, ❓) - if isnothing(info) unlock(slot);continue end - if now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + if isnothing(info) + unlock(slot) + continue + end + if now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time # TODO this should be part of the query interface, not using non-public implementation details untag!(slot, info.id) traceout!(slot) msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) @@ -44,17 +52,17 @@ end #delete old history tags info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) - if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time # TODO this should be part of the query interface, not using non-public implementation details untag!(slot, info.id) end #delete old EntanglementDelete tags info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) - if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time + if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time # TODO this should be part of the query interface, not using non-public implementation details untag!(slot, info.id) end unlock(slot) end @yield timeout(prot.sim, prot.period) end -end \ No newline at end of file +end From ebb3cbd7e7fd9ec513f7cd3e3956a8f8fd923b35 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 2 Jul 2024 23:51:10 -0400 Subject: [PATCH 60/93] minor cleanup of examples --- docs/src/howto/repeatergrid/repeatergrid.md | 2 +- .../1a_async_interactive_visualization.jl | 13 +++++++------ .../repeatergrid/1b_async_wglmakie_interactive.jl | 13 +++++++------ .../2a_sync_interactive_visualization.jl | 13 +++++++------ .../repeatergrid/2b_sync_wglmakie_interactive.jl | 11 ++++++----- examples/repeatergrid/setup.jl | 10 ++++++---- 6 files changed, 34 insertions(+), 28 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index 55901fe..d561058 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -11,7 +11,7 @@ This section provides a detailed walkthrough of how QuantumSavory.jl can be used For this example, we consider a square grid topology in which each node is connected to its nearest neighbors. The registers act as repeater nodes. The nodes on the diagonal corners are Alice and Bob, the two special nodes that the network is trying to entangle through generating link-level entanglement at each edge and performing appropriate swaps at each node. -The goal is to establish entanglement between Alice and Bob by routing entanglement through any of the possible paths(horizontal or vertical) formed by local entanglement links and then swapping those links by performing entanglement swaps. +The goal is to establish entanglement between Alice and Bob by routing entanglement through any of the possible paths (horizontal or vertical) formed by local entanglement links and then swapping those links by performing entanglement swaps. This employs functionality from the `ProtocolZoo` module of QuantumSavory to run the following Quantum Networking protocols: diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index 9face67..276350e 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -1,10 +1,11 @@ using GLMakie +# TODO significant code duplication with the other examples include("setup.jl") sim, net, graph, consumer, params... = prepare_simulation() -fig = Figure(;size=(800, 600)) +fig = Figure(;size=(1200, 850)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D @@ -23,12 +24,12 @@ histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes hist!(histaxis, Δts) # sliders -sg = SliderGrid( +sg = SliderGrid( # TODO significant code duplication with the other examples fig[3,1], (label="Probability of success of Entanglement generation at each attempt", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", - range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.5:10.0, format="{:.3f}", startvalue=0.001), (label="Wait time after failure to lock qubits for a swap", range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", @@ -36,9 +37,9 @@ sg = SliderGrid( (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Period of time between subsequent queries at the DecoherenceProtocol", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), width = 600, tellheight = false) diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl index a20f877..d05fe83 100644 --- a/examples/repeatergrid/1b_async_wglmakie_interactive.jl +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -2,6 +2,7 @@ using WGLMakie WGLMakie.activate!() import Bonito using Markdown +# TODO significant code duplication with the other examples include("setup.jl") @@ -12,7 +13,7 @@ function prepare_singlerun() sim, net, graph, consumer, params... = prepare_simulation() # Prepare the main figure - fig = Figure(size=(1200, 800)) + fig = Figure(;size=(1200, 850)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) @@ -30,12 +31,12 @@ function prepare_singlerun() hist!(histaxis, Δts) # sliders - sg = SliderGrid( + sg = SliderGrid( # TODO significant code duplication with the other examples fig[3,1], (label="Probability of success of Entanglement generation at each attempt", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", - range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.5:10.0, format="{:.3f}", startvalue=0.001), (label="Wait time after failure to lock qubits for a swap", range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", @@ -43,9 +44,9 @@ function prepare_singlerun() (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Period of time between subsequent queries at the DecoherenceProtocol", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), width = 600, tellheight = false) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index 54b4747..0a6993a 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -1,10 +1,11 @@ using GLMakie +# TODO significant code duplication with the other examples include("setup.jl") sim, net, graph, consumer, params... = prepare_simulation(;sync=true) -fig = Figure(;size=(800, 600)) +fig = Figure(;size=(1200, 850)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D @@ -23,12 +24,12 @@ histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes hist!(histaxis, Δts) # sliders -sg = SliderGrid( +sg = SliderGrid( # TODO significant code duplication with the other examples fig[3,1], (label="Probability of success of Entanglement generation at each attempt", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", - range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.5:10.0, format="{:.3f}", startvalue=0.001), (label="Wait time after failure to lock qubits for a swap", range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", @@ -36,9 +37,9 @@ sg = SliderGrid( (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Period of time between subsequent queries at the DecoherenceProtocol", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), width = 600, tellheight = false) diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl index fcfbaa6..47be3d5 100644 --- a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -2,6 +2,7 @@ using WGLMakie WGLMakie.activate!() import Bonito using Markdown +# TODO significant code duplication with the other examples include("setup.jl") @@ -12,7 +13,7 @@ function prepare_singlerun() sim, net, graph, consumer, params... = prepare_simulation(;sync=true) # Prepare the main figure - fig = Figure(size=(1200, 800)) + fig = Figure(;size=(1200, 850)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) @@ -33,9 +34,9 @@ function prepare_singlerun() sg = SliderGrid( fig[3,1], (label="Probability of success of Entanglement generation at each attempt", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", - range=0.001:0.5:10.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.5:10.0, format="{:.3f}", startvalue=0.001), (label="Wait time after failure to lock qubits for a swap", range=0.1:0.05:1.0, format="{:.2f}", startvalue=0.1), (label="Retention time for an unused qubit", @@ -43,9 +44,9 @@ function prepare_singlerun() (label="Time before a qubit's retention time runs out (for `agelimit`)", range=0.1:0.5:10.0, format="{:.2f}", startvalue=0.5), (label="Period of time between subsequent queries at the consumer", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Period of time between subsequent queries at the DecoherenceProtocol", - range=0.001:0.05:1.0, format="{:.2f}", startvalue=0.001), + range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), width = 600, tellheight = false) diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl index da21d8b..9d3baf3 100644 --- a/examples/repeatergrid/setup.jl +++ b/examples/repeatergrid/setup.jl @@ -5,8 +5,9 @@ using ConcurrentSim using ResumableFunctions using NetworkLayout -# Predicate function for swap decisions -"""A predicate function that checks if a remote node is in the appropriate quadrant with respect to the local node.""" +"""Predicate function for swap decisions + +Checks if a remote node is in the appropriate quadrant with respect to the local node.""" function check_nodes(net, c_node, node; low=true) n = Int(sqrt(size(net.graph)[1])) # grid size c_x = c_node%n == 0 ? c_node ÷ n : (c_node ÷ n) + 1 @@ -16,8 +17,9 @@ function check_nodes(net, c_node, node; low=true) return low ? (c_x - x) >= 0 && (c_y - y) >= 0 : (c_x - x) <= 0 && (c_y - y) <= 0 end -#Choosing function to pick from swap candidates -"""A function that chooses the node in the appropriate quadrant that is furthest from the local node.""" +"""Choosing function to pick from swap candidates + +Chooses the node in the appropriate quadrant that is furthest from the local node.""" function choose_node(net, node, arr; low=true) grid_size = Int(sqrt(size(net.graph)[1])) return low ? argmax((distance.(grid_size, node, arr))) : argmin((distance.(grid_size, node, arr))) From d6d487b79637d3d0f832ddf7009ab137c9a4a2bf Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Wed, 3 Jul 2024 00:03:36 -0400 Subject: [PATCH 61/93] some notes for the new queries isassigned error --- src/queries.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/queries.jl b/src/queries.jl index 672d416..e0ef5d9 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -407,7 +407,7 @@ function findfreeslot(reg::Register; randomize=false, margin=0) end end -struct NotAssignedError <: Exception +struct NotAssignedError <: Exception # TODO use this in all places where we are throwing something on isassigned (maybe rename to IsAssignedError and check whether we need to keep `f` as part of it (might already be provided by the stacktrace) and check it does not allocate even when the error is not triggered) msg f end @@ -429,4 +429,4 @@ end function Base.isassigned(r::Register,i::Int) # TODO erase r.stateindices[i] != 0 # TODO this also usually means r.staterefs[i] !== nothing - choose one and make things consistent end -Base.isassigned(r::RegRef) = isassigned(r.reg, r.idx) \ No newline at end of file +Base.isassigned(r::RegRef) = isassigned(r.reg, r.idx) From 62ca1743c2a4eec5b1fb34044ed91d2045dac93d Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Wed, 3 Jul 2024 00:05:20 -0400 Subject: [PATCH 62/93] update CHANGELOG --- CHANGELOG.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75484f6..789a8dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,11 @@ # News -## v0.4.2 - dev +## v0.4.2 - 2024-07-03 - Develop `CutoffProt` to deal with deadlocks in a simulation -- Expand `SwapperProt` into `SwapperKeeper` and `SwapperShedder` to work with `CutoffProt` in asynchronous and synchronous mode -- Tutorial for entanglement distribution on a grid -- Interactive examples using `SwapperKeeper` and `SwapperShedder` for simulation and visualization -- WebGL demos for the two ways of doing swapping and decoherence. +- Expand `SwapperProt` with `agelimit` to permit cutoff policies (with `CutoffProt`) +- Tutorial and interactive examples for entanglement distribution on a grid with local-only knowledge - Bump QuantumSymbolics compat bound and bump julia compat to 1.10. - Bump QuantumSymbolics and QuantumOpticsBase compat bound and bump julia compat to 1.10. From 5d26084ff21aa9ff43707b7ce988a5727461be8b Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 2 Jul 2024 12:45:58 -0400 Subject: [PATCH 63/93] Apply noise to qubtis --- examples/repeatergrid/setup.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl index 9d3baf3..a44c2cb 100644 --- a/examples/repeatergrid/setup.jl +++ b/examples/repeatergrid/setup.jl @@ -43,7 +43,7 @@ function prepare_simulation(;sync=false) # The graph of network connectivity graph = grid([n,n]) - net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) + net = RegisterNet(graph, [Register(regsize, T1Decay(10.0)) for i in 1:n^2]) sim = get_time_tracker(net) ##Setup the networking protocols running between each of the nodes From 958bd059af27a763983901ddeab6132f0bc6d1bf Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 3 Jul 2024 21:09:18 -0400 Subject: [PATCH 64/93] fix1 for race condition --- src/ProtocolZoo/ProtocolZoo.jl | 8 ++++---- src/ProtocolZoo/swapping.jl | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index 64233b9..f553714 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -124,8 +124,8 @@ Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, ta """ $TYPEDEF -This tag arrives as a message from a remote node's Cutoff Protocol to which the current node used to be entangled, to -update the classical metadata of the entangled slot and empty it. +This tag arrives as a message from a remote node's Cutoff Protocol to which the current node was entangled, to +update the classical metadata of the entangled slot and empty it. It is also stored at a node to handle incoming `EntanglementUpdate` and `EntanglementDelete` messages. $TYPEDFIELDS @@ -338,7 +338,7 @@ end # Finally, if there the history of a swap is not present in the log anymore, # it must be because a delete message was received, and forwarded, - # and the swap history was deleted, and replaced with a delete history. + # and the entanglement history was deleted, and replaced with an entanglement delete tag. if !isnothing(querydelete!(localslot, EntanglementDelete, prot.node, localslot.idx, pastremotenode, pastremoteslotid)) #deletion from both sides of the swap, deletion msg when both qubits of a pair are deleted, or when EU arrives after ED at swap node with two simultaneous swaps and deletion on one side if !(isnothing(updategate)) # EntanglementUpdate # to handle a possible delete-swap-swap case, we need to update the EntanglementDelete tag @@ -351,7 +351,7 @@ end 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` or `EntanglementDelete` tags). This might have happened due to `CutoffProt` deleting qubits while swaps are happening. Make sure that the retentian times in `CutoffProt` are sufficiently larger than the `agelimit` in `SwapperProt`. Otherwise is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.") + 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` or `EntanglementDelete` tags). This might have happened due to `CutoffProt` deleting qubits while swaps are happening. Make sure that the retention times in `CutoffProt` are sufficiently larger than the `agelimit` in `SwapperProt`. Otherwise, this is a bug in the protocol and should not happen -- please report an issue at QuantumSavory's repository.") end end @debug "EntanglementTracker @$(prot.node): Starting message wait at $(now(prot.sim)) with MessageBuffer containing: $(mb.buffer)" diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index f755d1b..bfa764f 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -75,8 +75,6 @@ end (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, 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 @@ -85,6 +83,9 @@ end 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) + + @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) uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() From 46eb0a40f9ea53a66e97c8d9f30446cd6c075153 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 3 Jul 2024 23:37:08 -0400 Subject: [PATCH 65/93] Why does this work? --- src/ProtocolZoo/swapping.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index bfa764f..f46e26c 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -76,6 +76,8 @@ end (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, 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) @@ -84,9 +86,6 @@ end # 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) - @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) - uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() xmeas, zmeas = swapcircuit(q1, q2) From 8d0f1e41d0d4e81de6702ffa95de58e85c1028ac Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 11 Jul 2024 11:36:01 -0400 Subject: [PATCH 66/93] Add new visualizations and edit readme --- .../1a_async_interactive_visualization.jl | 23 +++++++++++++++---- examples/repeatergrid/Readme.md | 5 ++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index 276350e..36dabd1 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -5,7 +5,7 @@ include("setup.jl") sim, net, graph, consumer, params... = prepare_simulation() -fig = Figure(;size=(1200, 850)) +fig = Figure(;size=(1200, 1100)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D @@ -19,13 +19,24 @@ txxs = @lift [Point2f(e[1],e[3]) for e in $entlog] Δts = @lift length($ts)>1 ? $ts[2:end] .- $ts[1:end-1] : [0.0] entlogaxis = Axis(fig[1,2], xlabel="Time", ylabel="Entanglement", title="Entanglement Successes") ylims!(entlogaxis, (-1.04,1.04)) -stem!(entlogaxis, tzzs) +stem!(entlogaxis, txxs) histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") hist!(histaxis, Δts) +avg_fids = @lift cumsum([e[3] for e in $entlog])./($ts) #avg fidelity per unit time +fid_info = @lift [Point2f(t,f) for (t,f) in zip($ts, $avg_fids)] +fid_axis = Axis(fig[3,1], xlabel="Time", ylabel="Avg. Fidelity", title="Time evolution of Average Fidelity") +lines!(fid_axis, fid_info) + +num_epr = @lift cumsum(ones(length($entlog)))./($ts) #avg number of pairs per unit time +num_epr_info = @lift [Point2f(t,n) for (t,n) in zip($ts, $num_epr)] +num_epr_axis = Axis(fig[3,2], xlabel="Time", title="Avg. Number of Entangled Pairs between Alice and Bob") +lines!(num_epr_axis, num_epr_info) + + # sliders sg = SliderGrid( # TODO significant code duplication with the other examples - fig[3,1], + fig[4,1], (label="Probability of success of Entanglement generation at each attempt", range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", @@ -57,8 +68,12 @@ step_ts = range(0, 1000, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) + ylims!(fid_axis, (0, 1.04)) + xlims!(fid_axis, max(0, t-50), 1+t) autolimits!(histaxis) + ylims!(num_epr_axis, (0, 4)) + xlims!(num_epr_axis, max(0, t-50), 1+t) end diff --git a/examples/repeatergrid/Readme.md b/examples/repeatergrid/Readme.md index e69de29..93459a4 100644 --- a/examples/repeatergrid/Readme.md +++ b/examples/repeatergrid/Readme.md @@ -0,0 +1,5 @@ +This example visualizes a quantum network attempting to distribute between the Alice and Bob user pair located on the diagonal of a grid topology where asynchronous messaging and queries are used for classical communication of entanglement information between modes using protocols like [`EntanglementTracker`](@ref) and [`SwapperProt`](@ref). Link-level-entanglement is generated between all the horizontal and vertical neighbors using an entanglement generation protocol called [`EntanglerProt`](@ref). As an entanglement link is established between the end users, it is consumed by a protocol named [`EntanglementConsumer`](@ref) which records the fidelity and time of consumption of the pair. Also, the qubits that remain unused beyond their `retention_time` are discarded by the [`CutoffProt`](@ref) This module provides two ways of running the simulation using: + +- [`SwapperProt`](@ref) and [`CutoffProt`](@ref) in an asynchrnous manner where they run independently and all the classical information about the quantum states is reconciled using asynchronous messages sent to the tracker. + +- [`SwapperProt`](@ref) does not use qubits that are to be thrown away by the [`CutoffProt`](@ref) by checking their `agelimit` parameter passed to it during initializaton. Here, there are no outgoing messages from the [`CutoffProt`](@ref) and everything is handled by being synchronous. \ No newline at end of file From ac0c27d91b1abc8cae825b7bf4a699077ee17aff Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 11 Jul 2024 11:40:56 -0400 Subject: [PATCH 67/93] typos --- docs/src/symbolics.md | 2 +- examples/repeatergrid/Readme.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/symbolics.md b/docs/src/symbolics.md index 63c3723..0ddb830 100644 --- a/docs/src/symbolics.md +++ b/docs/src/symbolics.md @@ -203,4 +203,4 @@ express(MixedState(X1)/2+SProjector(Z1)/2, CliffordRepr()) !!! warning "Stabilizer state expressions" - The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using sumation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and sumation of density matrices. \ No newline at end of file + The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and sumation of density matrices. \ No newline at end of file diff --git a/examples/repeatergrid/Readme.md b/examples/repeatergrid/Readme.md index 93459a4..18a9574 100644 --- a/examples/repeatergrid/Readme.md +++ b/examples/repeatergrid/Readme.md @@ -1,5 +1,5 @@ This example visualizes a quantum network attempting to distribute between the Alice and Bob user pair located on the diagonal of a grid topology where asynchronous messaging and queries are used for classical communication of entanglement information between modes using protocols like [`EntanglementTracker`](@ref) and [`SwapperProt`](@ref). Link-level-entanglement is generated between all the horizontal and vertical neighbors using an entanglement generation protocol called [`EntanglerProt`](@ref). As an entanglement link is established between the end users, it is consumed by a protocol named [`EntanglementConsumer`](@ref) which records the fidelity and time of consumption of the pair. Also, the qubits that remain unused beyond their `retention_time` are discarded by the [`CutoffProt`](@ref) This module provides two ways of running the simulation using: -- [`SwapperProt`](@ref) and [`CutoffProt`](@ref) in an asynchrnous manner where they run independently and all the classical information about the quantum states is reconciled using asynchronous messages sent to the tracker. +- [`SwapperProt`](@ref) and [`CutoffProt`](@ref) in an asynchronous manner where they run independently and all the classical information about the quantum states is reconciled using asynchronous messages sent to the tracker. -- [`SwapperProt`](@ref) does not use qubits that are to be thrown away by the [`CutoffProt`](@ref) by checking their `agelimit` parameter passed to it during initializaton. Here, there are no outgoing messages from the [`CutoffProt`](@ref) and everything is handled by being synchronous. \ No newline at end of file +- [`SwapperProt`](@ref) does not use qubits that are to be thrown away by the [`CutoffProt`](@ref) by checking their `agelimit` parameter passed to it during initialization. Here, there are no outgoing messages from the [`CutoffProt`](@ref) and everything is handled by being synchronous. \ No newline at end of file From 6fee642298ffb79e8a564f0e7ad70f6718c6bfe4 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 11 Jul 2024 11:44:16 -0400 Subject: [PATCH 68/93] typo --- docs/src/symbolics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/symbolics.md b/docs/src/symbolics.md index 0ddb830..c49fe7c 100644 --- a/docs/src/symbolics.md +++ b/docs/src/symbolics.md @@ -203,4 +203,4 @@ express(MixedState(X1)/2+SProjector(Z1)/2, CliffordRepr()) !!! warning "Stabilizer state expressions" - The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and sumation of density matrices. \ No newline at end of file + The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices. \ No newline at end of file From 86e7176859b916cbcfe8c02f1142c7cbfc254ca4 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 17 Jul 2024 16:25:11 -0400 Subject: [PATCH 69/93] move timeout before unlock --- src/ProtocolZoo/swapping.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index f46e26c..d881242 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -77,7 +77,6 @@ end (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, 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) @@ -99,6 +98,7 @@ end msg2 = Tag(EntanglementUpdateZ, prot.node, q2.idx, tag2[3], tag1[2], tag1[3], zmeas) put!(channel(prot.net, prot.node=>tag2[2]; permit_forward=true), msg2) @debug "SwapperProt @$(prot.node)|round $(round): Send message to $(tag2[2]) | message=`$msg2` | time = $(now(prot.sim))" + @yield timeout(prot.sim, prot.local_busy_time) unlock(q1) unlock(q2) rounds==-1 || (rounds -= 1) From eb92e474494dac9f81ac90069b747debddbfbbbd Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 18 Jul 2024 15:02:16 -0400 Subject: [PATCH 70/93] Rerun CI? --- src/ProtocolZoo/swapping.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index d881242..c3dcb47 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -76,7 +76,7 @@ end (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 lock(q1) & lock(q2) # this should not really need a yield thanks to `findswapablequbits` which queries only for unlocked qubits, but it is better to be defensive 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) From f04c2fe1130485ad194bbf850279c2e535cb7baa Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 23 Jul 2024 16:40:49 -0400 Subject: [PATCH 71/93] fix --- src/ProtocolZoo/ProtocolZoo.jl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index f553714..bf4275e 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -286,14 +286,16 @@ end # Check if the local slot is still present and believed to be entangled. # We will need to perform a correction operation due to the swap or a deletion due to the qubit being thrown out, # but there will be no message forwarding necessary. + @debug "EntanglementTracker @$(prot.node): EntanglementCounterpart requesting lock at $(now(prot.sim))" + @yield lock(localslot) + @debug "EntanglementTracker @$(prot.node): EntanglementCounterpart getting lock at $(now(prot.sim))" counterpart = querydelete!(localslot, EntanglementCounterpart, pastremotenode, pastremoteslotid) + unlock(localslot) if !isnothing(counterpart) - time_before_lock = now(prot.sim) - @debug "EntanglementTracker @$(prot.node): EntanglementCounterpart requesting lock at $(now(prot.sim))" + # time_before_lock = now(prot.sim) @yield lock(localslot) - @debug "EntanglementTracker @$(prot.node): EntanglementCounterpart getting lock at $(now(prot.sim))" - time_after_lock = now(prot.sim) - time_before_lock != time_after_lock && @debug "EntanglementTracker @$(prot.node): Needed Δt=$(time_after_lock-time_before_lock) to get a lock" + # time_after_lock = now(prot.sim) + # time_before_lock != time_after_lock && @debug "EntanglementTracker @$(prot.node): Needed Δt=$(time_after_lock-time_before_lock) to get a lock" if !isassigned(localslot) 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.") # TODO make it configurable whether an error is thrown and plug it into the logging module From fdfc868a0d6d0acabb1ce98a239ee441721d1c97 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Thu, 25 Jul 2024 20:04:52 -0400 Subject: [PATCH 72/93] Some touches to the visualization code, correction in avg fidelity expression --- .../1a_async_interactive_visualization.jl | 2 +- .../1b_async_wglmakie_interactive.jl | 18 ++++++++++++++++-- .../2a_sync_interactive_visualization.jl | 18 ++++++++++++++++-- .../2b_sync_wglmakie_interactive.jl | 18 ++++++++++++++++-- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index 36dabd1..00317cc 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -23,7 +23,7 @@ stem!(entlogaxis, txxs) histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") hist!(histaxis, Δts) -avg_fids = @lift cumsum([e[3] for e in $entlog])./($ts) #avg fidelity per unit time +avg_fids = @lift cumsum([e[3] for e in $entlog])./cumsum(ones(length($entlog))) #avg fidelity per unit time fid_info = @lift [Point2f(t,f) for (t,f) in zip($ts, $avg_fids)] fid_axis = Axis(fig[3,1], xlabel="Time", ylabel="Avg. Fidelity", title="Time evolution of Average Fidelity") lines!(fid_axis, fid_info) diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl index d05fe83..7fe2ab1 100644 --- a/examples/repeatergrid/1b_async_wglmakie_interactive.jl +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -13,7 +13,7 @@ function prepare_singlerun() sim, net, graph, consumer, params... = prepare_simulation() # Prepare the main figure - fig = Figure(;size=(1200, 850)) + fig = Figure(;size=(1200, 1100)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) @@ -30,6 +30,16 @@ function prepare_singlerun() histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") hist!(histaxis, Δts) + avg_fids = @lift cumsum([e[3] for e in $entlog])./cumsum(ones(length($entlog))) #avg fidelity per unit time + fid_info = @lift [Point2f(t,f) for (t,f) in zip($ts, $avg_fids)] + fid_axis = Axis(fig[3,1], xlabel="Time", ylabel="Avg. Fidelity", title="Time evolution of Average Fidelity") + lines!(fid_axis, fid_info) + + num_epr = @lift cumsum(ones(length($entlog)))./($ts) #avg number of pairs per unit time + num_epr_info = @lift [Point2f(t,n) for (t,n) in zip($ts, $num_epr)] + num_epr_axis = Axis(fig[3,2], xlabel="Time", title="Avg. Number of Entangled Pairs between Alice and Bob") + lines!(num_epr_axis, num_epr_info) + # sliders sg = SliderGrid( # TODO significant code duplication with the other examples fig[3,1], @@ -67,10 +77,14 @@ function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, run for t in step_ts run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) + ylims!(fid_axis, (0, 1.04)) + xlims!(fid_axis, max(0, t-50), 1+t) autolimits!(histaxis) + ylims!(num_epr_axis, (0, 4)) + xlims!(num_epr_axis, max(0, t-50), 1+t) end running[] = nothing end diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index 0a6993a..1f5adeb 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -5,7 +5,7 @@ include("setup.jl") sim, net, graph, consumer, params... = prepare_simulation(;sync=true) -fig = Figure(;size=(1200, 850)) +fig = Figure(;size=(1200, 1100)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D @@ -23,6 +23,16 @@ stem!(entlogaxis, tzzs) histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") hist!(histaxis, Δts) +avg_fids = @lift cumsum([e[3] for e in $entlog])./cumsum(ones(length($entlog))) #avg fidelity per unit time +fid_info = @lift [Point2f(t,f) for (t,f) in zip($ts, $avg_fids)] +fid_axis = Axis(fig[3,1], xlabel="Time", ylabel="Avg. Fidelity", title="Time evolution of Average Fidelity") +lines!(fid_axis, fid_info) + +num_epr = @lift cumsum(ones(length($entlog)))./($ts) #avg number of pairs per unit time +num_epr_info = @lift [Point2f(t,n) for (t,n) in zip($ts, $num_epr)] +num_epr_axis = Axis(fig[3,2], xlabel="Time", title="Avg. Number of Entangled Pairs between Alice and Bob") +lines!(num_epr_axis, num_epr_info) + # sliders sg = SliderGrid( # TODO significant code duplication with the other examples fig[3,1], @@ -57,8 +67,12 @@ step_ts = range(0, 1000, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) + ylims!(fid_axis, (0, 1.04)) + xlims!(fid_axis, max(0, t-50), 1+t) autolimits!(histaxis) + ylims!(num_epr_axis, (0, 4)) + xlims!(num_epr_axis, max(0, t-50), 1+t) end diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl index 47be3d5..5691173 100644 --- a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -13,7 +13,7 @@ function prepare_singlerun() sim, net, graph, consumer, params... = prepare_simulation(;sync=true) # Prepare the main figure - fig = Figure(;size=(1200, 850)) + fig = Figure(;size=(1200, 1100)) # the network part of the visualization layout = SquareGrid(cols=:auto, dx=30.0, dy=-30.0)(graph) # provided by NetworkLayout, meant to simplify plotting of graphs in 2D _, ax, _, obs = registernetplot_axis(fig[1:2,1], net;registercoords=layout) @@ -30,6 +30,16 @@ function prepare_singlerun() histaxis = Axis(fig[2,2], xlabel="ΔTime", title="Histogram of Time to Successes") hist!(histaxis, Δts) + avg_fids = @lift cumsum([e[3] for e in $entlog])./cumsum(ones(length($entlog))) #avg fidelity per unit time + fid_info = @lift [Point2f(t,f) for (t,f) in zip($ts, $avg_fids)] + fid_axis = Axis(fig[3,1], xlabel="Time", ylabel="Avg. Fidelity", title="Time evolution of Average Fidelity") + lines!(fid_axis, fid_info) + + num_epr = @lift cumsum(ones(length($entlog)))./($ts) #avg number of pairs per unit time + num_epr_info = @lift [Point2f(t,n) for (t,n) in zip($ts, $num_epr)] + num_epr_axis = Axis(fig[3,2], xlabel="Time", title="Avg. Number of Entangled Pairs between Alice and Bob") + lines!(num_epr_axis, num_epr_info) + # sliders sg = SliderGrid( fig[3,1], @@ -67,10 +77,14 @@ function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, run for t in step_ts run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) + ylims!(fid_axis, (0, 1.04)) + xlims!(fid_axis, max(0, t-50), 1+t) autolimits!(histaxis) + ylims!(num_epr_axis, (0, 4)) + xlims!(num_epr_axis, max(0, t-50), 1+t) end running[] = nothing end From 04ae501aa261623beeb1c717199d1d814294fbd1 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 30 Jul 2024 13:53:37 -0400 Subject: [PATCH 73/93] comment out offending code in docs, add type annotation in isolderthan --- docs/src/visualizations.md | 11 ++++++----- src/queries.jl | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index 74be69b..2c68f08 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -65,12 +65,13 @@ fig And here with some extra tag metadata. -```@example vis -tag!(net[2,3], :specialplace, 1, 2) -tag!(net[2,3], :otherdata, 3, 4) -QuantumSavory.showmetadata(fig,ax,plt,2,3) -fig + +# tag!(net[2,3], :specialplace, 1, 2) +# tag!(net[2,3], :otherdata, 3, 4) +# QuantumSavory.showmetadata(fig,ax,plt,2,3) +# fig ``` +--> ## The state of locks and various metadata in the network diff --git a/src/queries.jl b/src/queries.jl index e0ef5d9..55c3523 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -418,7 +418,7 @@ function Base.showerror(io::IO, err::NotAssignedError) println("In function: $(err.f)") end -function isolderthan(slot::RegRef, time_left) +function isolderthan(slot::RegRef, time_left::Float64) if !isassigned(slot) throw(NotAssignedError("Slot must be assigned with a quantum state before checking coherence.", isolderthan)) end id = query(slot, QuantumSavory.ProtocolZoo.EntanglementCounterpart, ❓, ❓).id slot_time = slot.reg.tag_info[id][3] From b85870db2a31040d8f725e488743d4f0a7a07827 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 31 Jul 2024 14:03:45 -0400 Subject: [PATCH 74/93] bump jet lower bound --- test/test_jet.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_jet.jl b/test/test_jet.jl index 1db05ca..a1a0db8 100644 --- a/test/test_jet.jl +++ b/test/test_jet.jl @@ -37,5 +37,5 @@ rep = report_package("QuantumSavory"; @show length(JET.get_reports(rep)) @show rep -@test length(JET.get_reports(rep)) <= 129 +@test length(JET.get_reports(rep)) <= 139 @test_broken length(JET.get_reports(rep)) == 0 From 870ccd158d569382312bd1664ba74eaa305d2c08 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 10 Aug 2024 17:20:34 -0400 Subject: [PATCH 75/93] docs fix --- docs/src/symbolics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/symbolics.md b/docs/src/symbolics.md index c49fe7c..6111486 100644 --- a/docs/src/symbolics.md +++ b/docs/src/symbolics.md @@ -203,4 +203,4 @@ express(MixedState(X1)/2+SProjector(Z1)/2, CliffordRepr()) !!! warning "Stabilizer state expressions" - The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices. \ No newline at end of file + The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as `SProjector`, [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices. \ No newline at end of file From 31b7d7176094bacd72585b1d8409cec074035137 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 10 Aug 2024 17:27:10 -0400 Subject: [PATCH 76/93] fix commenting in visualizations.md --- docs/src/visualizations.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index 2c68f08..ae3f4de 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -65,13 +65,12 @@ fig And here with some extra tag metadata. - -# tag!(net[2,3], :specialplace, 1, 2) -# tag!(net[2,3], :otherdata, 3, 4) -# QuantumSavory.showmetadata(fig,ax,plt,2,3) -# fig ``` ---> +tag!(net[2,3], :specialplace, 1, 2) +tag!(net[2,3], :otherdata, 3, 4) +QuantumSavory.showmetadata(fig,ax,plt,2,3) +fig +``` ## The state of locks and various metadata in the network From 48ba2cde62192cba58e32365388eed9b0445a967 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 10 Aug 2024 18:40:27 -0400 Subject: [PATCH 77/93] remove nsubsystems(Nothing) --- src/baseops/subsystemcompose.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/baseops/subsystemcompose.jl b/src/baseops/subsystemcompose.jl index 40a9fb5..0e417f4 100644 --- a/src/baseops/subsystemcompose.jl +++ b/src/baseops/subsystemcompose.jl @@ -2,7 +2,6 @@ nsubsystems(s::StateRef) = length(s.registers) # nsubsystems(s.state[]) TODO thi nsubsystems_padded(s::StateRef) = nsubsystems(s.state[]) nsubsystems(r::Register) = length(r.staterefs) nsubsystems(r::RegRef) = 1 -nsubsystems(::Nothing) = 1 # TODO consider removing this and reworking the functions that depend on it. E.g., a reason to have it when performing a project_traceout measurement on a state that contains only one subsystem function swap!(reg1::Register, reg2::Register, i1::Int, i2::Int; time=nothing) if reg1===reg2 && i1==i2 From 55062c2f8cec79a207d95e6edb90aabbe8b5f668 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Sat, 10 Aug 2024 19:18:24 -0400 Subject: [PATCH 78/93] undo previous experimental commit --- src/baseops/subsystemcompose.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/baseops/subsystemcompose.jl b/src/baseops/subsystemcompose.jl index 0e417f4..f5048c9 100644 --- a/src/baseops/subsystemcompose.jl +++ b/src/baseops/subsystemcompose.jl @@ -2,6 +2,7 @@ nsubsystems(s::StateRef) = length(s.registers) # nsubsystems(s.state[]) TODO thi nsubsystems_padded(s::StateRef) = nsubsystems(s.state[]) nsubsystems(r::Register) = length(r.staterefs) nsubsystems(r::RegRef) = 1 +nsubsystems(r::Nothing) = 1 # TODO consider removing this and reworking the functions that depend on it. E.g., a reason to have it when performing a project_traceout measurement on a state that contains only one subsystem function swap!(reg1::Register, reg2::Register, i1::Int, i2::Int; time=nothing) if reg1===reg2 && i1==i2 From 43d42b28dc331ab076891bc28ea9ca1666e5c968 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Mon, 19 Aug 2024 16:02:38 -0400 Subject: [PATCH 79/93] add new tests, bump jet count again after merging master --- test/test_jet.jl | 2 +- test/test_protocolzoo_cutoffprot.jl | 31 ++++++++++++ .../test_protocolzoo_entanglement_consumer.jl | 6 +-- ...t_protocolzoo_entanglement_tracker_grid.jl | 48 ++++++++++++++++++- 4 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 test/test_protocolzoo_cutoffprot.jl diff --git a/test/test_jet.jl b/test/test_jet.jl index 6fd9095..84b2905 100644 --- a/test/test_jet.jl +++ b/test/test_jet.jl @@ -38,5 +38,5 @@ rep = report_package("QuantumSavory"; @show length(JET.get_reports(rep)) @show rep -@test length(JET.get_reports(rep)) <= 133 +@test length(JET.get_reports(rep)) <= 145 @test_broken length(JET.get_reports(rep)) == 0 diff --git a/test/test_protocolzoo_cutoffprot.jl b/test/test_protocolzoo_cutoffprot.jl new file mode 100644 index 0000000..1bdfd65 --- /dev/null +++ b/test/test_protocolzoo_cutoffprot.jl @@ -0,0 +1,31 @@ +using QuantumSavory +using QuantumSavory.ProtocolZoo + +using ConcurrentSim +using ResumableFunctions + +using Test + +if isinteractive() + using Logging + logger = ConsoleLogger(Logging.Debug; meta_formatter=(args...)->(:black,"","")) + global_logger(logger) + println("Logger set to debug") +end + +net = RegisterNet([Register(1), Register(1)]) +sim = get_time_tracker(net) +initialize!((net[1][1], net[2][1]), (Z1⊗Z1+Z2⊗Z2)/(sqrt(2.0))) +tag!(net[1][1], EntanglementCounterpart, 2, 1) +tag!(net[2][1], EntanglementCounterpart, 1, 1) + +cprot = CutoffProt(sim, net, 1; retention_time=3.0) +@process cprot() + +run(sim, 2.0) +@test isassigned(net[1][1]) +@test isassigned(net[2][1]) + +run(sim, 6.0) +@test !isassigned(net[1][1]) +@test isassigned(net[2][1]) \ No newline at end of file diff --git a/test/test_protocolzoo_entanglement_consumer.jl b/test/test_protocolzoo_entanglement_consumer.jl index 4f34236..bc3878f 100644 --- a/test/test_protocolzoo_entanglement_consumer.jl +++ b/test/test_protocolzoo_entanglement_consumer.jl @@ -39,10 +39,8 @@ for n in 3:30 for i in 1:length(econ.log) - if !isnothing(econ.log[i][2]) - @test econ.log[i][2] ≈ 1.0 - @test econ.log[i][3] ≈ 1.0 - end + @test econ.log[i][2] ≈ 1.0 + @test econ.log[i][3] ≈ 1.0 end end diff --git a/test/test_protocolzoo_entanglement_tracker_grid.jl b/test/test_protocolzoo_entanglement_tracker_grid.jl index 5186558..9fbee78 100644 --- a/test/test_protocolzoo_entanglement_tracker_grid.jl +++ b/test/test_protocolzoo_entanglement_tracker_grid.jl @@ -228,5 +228,49 @@ end # More tests of 2D rectangular grids with the full stack of protocols, # but also now with an unlimited number of rounds and an entanglement consumer. -#TODO -@test_broken false + +n = 6 # the size of the square grid network (n × n) +regsize = 20 # the size of the quantum registers at each node + +graph = grid([n,n]) +net = RegisterNet(graph, [Register(regsize) for i in 1:n^2]) + +sim = get_time_tracker(net) + +# each edge is capable of generating raw link-level entanglement +for (;src, dst) in edges(net) + eprot = EntanglerProt(sim, net, src, dst; rounds=-1, randomize=true) + @process eprot() +end + +# each node except the corners on one of the diagonals is capable of swapping entanglement +for i in 2:(n^2 - 1) + l(x) = check_nodes(net, i, x) + h(x) = check_nodes(net, i, x; low=false) + cL(arr) = choose_node(net, i, arr) + cH(arr) = choose_node(net, i, arr; low=false) + swapper = SwapperProt(sim, net, i; nodeL = l, nodeH = h, chooseL = cL, chooseH = cH, rounds=-1) + @process swapper() +end + +# each node is running entanglement tracking to keep track of classical data about the entanglement +for v in vertices(net) + tracker = EntanglementTracker(sim, net, v) + @process tracker() +end + +# a mock entanglement consumer between the two corners of the grid +consumer = EntanglementConsumer(sim, net, 1, n^2) +@process consumer() + +# at each node we discard the qubits that have decohered after a certain cutoff time +for v in vertices(net) + cutoffprot = CutoffProt(sim, net, v) + @process cutoffprot() +end +run(sim, 400) + +for i in 1:length(consumer.log) + @test consumer.log[i][2] ≈ 1.0 + @test consumer.log[i][3] ≈ 1.0 +end \ No newline at end of file From bb0d81a1b52f22bf004ed378b7e5f3cad3cffa4a Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Tue, 20 Aug 2024 15:35:21 -0400 Subject: [PATCH 80/93] add cutoffprot tests to runtests --- test/runtests.jl | 1 + test/test_jet.jl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 4a2e9c6..942565e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -37,6 +37,7 @@ println("Starting tests with $(Threads.nthreads()) threads out of `Sys.CPU_THREA @doset "protocolzoo_entanglement_tracker_grid" @doset "protocolzoo_switch" @doset "protocolzoo_throws" +@doset "protocolzoo_cutoffprot" @doset "circuitzoo_api" @doset "circuitzoo_ent_swap" diff --git a/test/test_jet.jl b/test/test_jet.jl index 84b2905..6933379 100644 --- a/test/test_jet.jl +++ b/test/test_jet.jl @@ -38,5 +38,5 @@ rep = report_package("QuantumSavory"; @show length(JET.get_reports(rep)) @show rep -@test length(JET.get_reports(rep)) <= 145 +@test length(JET.get_reports(rep)) <= 146 @test_broken length(JET.get_reports(rep)) == 0 From 02aa5d1d734716d64e770a2572d9daed1c091424 Mon Sep 17 00:00:00 2001 From: Abhishek Bhatt Date: Wed, 21 Aug 2024 13:06:27 -0400 Subject: [PATCH 81/93] use record instead of a for loop in congestionchain example --- examples/congestionchain/1_visualization.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/congestionchain/1_visualization.jl b/examples/congestionchain/1_visualization.jl index ab58e4b..5ac764e 100644 --- a/examples/congestionchain/1_visualization.jl +++ b/examples/congestionchain/1_visualization.jl @@ -45,7 +45,8 @@ scatter!(ax_fidZZ,ts,fidZZ,label="ZZ",color=(c2,0.1)) display(fig) step_ts = range(0, 1000, step=0.1) -for t in step_ts + +record(fig, "congestionchain.mp4", step_ts; framerate=50, visible=true) do t run(sim, t) ax.title = "t=$(t)" notify(obs) From 938448517c4c5520c13e926a6258746583014391 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 12:29:46 -0400 Subject: [PATCH 82/93] docs and changelog and version bump --- CHANGELOG.md | 7 ++++++- Project.toml | 2 +- docs/src/visualizations.md | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5842553..68b3376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,12 +2,17 @@ ## v0.5.0 - 2024-08-11 + - Develop `CutoffProt` to deal with deadlocks in a simulation - Expand `SwapperProt` with `agelimit` to permit cutoff policies (with `CutoffProt`) - Tutorial and interactive examples for entanglement distribution on a grid with local-only knowledge -- `observable` now takes a default value as a kwarg, i.e., you need to make the substitution `observable(regs, obs, 0.0; time)` ↦ `observable(regs, obs; something=0.0, time)` +- **(breaking)** `observable` now takes a default value as a kwarg, i.e., you need to make the substitution `observable(regs, obs, 0.0; time)` ↦ `observable(regs, obs; something=0.0, time)` - Bump QuantumSymbolics and QuantumOpticsBase compat bound and bump julia compat to 1.10. +## v0.4.2 - 2024-08-13 + +- Incorrect breaking release. It should have been 0.5 (see above). + ## v0.4.1 - 2024-06-05 - Significant improvements to the performance of `query`. diff --git a/Project.toml b/Project.toml index 93c1320..c7e7d91 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumSavory" uuid = "2de2e421-972c-4cb5-a0c3-999c85908079" authors = ["Stefan Krastanov "] -version = "0.4.2-dev" +version = "0.5" [deps] Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76" diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index ae3f4de..74be69b 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -65,7 +65,7 @@ fig And here with some extra tag metadata. -``` +```@example vis tag!(net[2,3], :specialplace, 1, 2) tag!(net[2,3], :otherdata, 3, 4) QuantumSavory.showmetadata(fig,ax,plt,2,3) From 8945686461b0659ddd95a0c9d9cfce68dcc4d65f Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 14:28:54 -0400 Subject: [PATCH 83/93] fix the documentation example --- docs/src/visualizations.md | 13 +++++++++---- ext/QuantumSavoryMakie/QuantumSavoryMakie.jl | 2 +- test/test_plotting_gl.jl | 20 ++++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/src/visualizations.md b/docs/src/visualizations.md index 74be69b..3ca2289 100644 --- a/docs/src/visualizations.md +++ b/docs/src/visualizations.md @@ -18,6 +18,7 @@ The [`registernetplot_axis`](@ref) function can be used to draw a given set of r ```@example vis using GLMakie +GLMakie.activate!() using QuantumSavory # create a network of qubit registers @@ -57,8 +58,12 @@ initialize!(network[1,1]) # hide initialize!(network[2,3], X₁) # hide initialize!((network[3,1],network[4,2]), X₁⊗Z₂) # hide apply!((network[2,3],network[3,1]), CNOT) # hide -fig = Figure(size=(400,400)) # hide -_, _, plt, obs = registernetplot_axis(fig[1,1],network) # hide +fig = Figure(size=(700,400)) # hide +_, ax, plt, obs = registernetplot_axis(fig[1,1],network) # hide +fig +``` + +```@example vis QuantumSavory.showmetadata(fig,ax,plt,1,1) fig ``` @@ -66,8 +71,8 @@ fig And here with some extra tag metadata. ```@example vis -tag!(net[2,3], :specialplace, 1, 2) -tag!(net[2,3], :otherdata, 3, 4) +tag!(network[2,3], :specialplace, 1, 2) +tag!(network[2,3], :otherdata, 3, 4) QuantumSavory.showmetadata(fig,ax,plt,2,3) fig ``` diff --git a/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl b/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl index 2aa6539..5f0740e 100644 --- a/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl +++ b/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl @@ -240,7 +240,7 @@ end function get_state_vis_string(backrefs, i) state, register, registeridx, slot, subsystem = backrefs[i] - tags = register.tags[slot] + tags = [ti.tag for ti in values(register.tag_info) if ti.slot==slot] tags_str = if isempty(tags) "not tagged" else diff --git a/test/test_plotting_gl.jl b/test/test_plotting_gl.jl index c9acda4..b168334 100644 --- a/test/test_plotting_gl.jl +++ b/test/test_plotting_gl.jl @@ -8,3 +8,23 @@ end @testset "arguments and observables and tags" begin include("test_plotting_2_tags_observables.jl") end + +using QuantumSavory + +@testset "data inspectors" begin # only available in GLMakie + # create a network of qubit registers + net = RegisterNet([Register(2),Register(3),Register(2),Register(5)]) + + # add some states, entangle a few slots, perform some gates + initialize!(net[1,1]) + initialize!(net[2,3], X₁) + initialize!((net[3,1],net[4,2]), X₁⊗Z₂) + apply!((net[2,3],net[3,1]), CNOT) + + # create the plot + fig = Figure(size=(800,400)) + _, ax, plt, obs = registernetplot_axis(fig[1,1],net) + + # check the data inspector tooltip functionality + @test Base.get_extension(QuantumSavory, :QuantumSavoryMakie).get_state_vis_string(plt.state_coords_backref[],1) == "Subsystem 1 of a state of 1 subsystems, stored in\nRegister 1 | Slot 1\n not tagged" +end From 367442a448253e95bd67fecd1cb8939e5588c1ff Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 14:31:47 -0400 Subject: [PATCH 84/93] undo SProjector removal now that it is public again --- docs/src/symbolics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/symbolics.md b/docs/src/symbolics.md index a59543f..2b13c67 100644 --- a/docs/src/symbolics.md +++ b/docs/src/symbolics.md @@ -202,4 +202,4 @@ express(MixedState(X1)/2+SProjector(Z1)/2, CliffordRepr()) ``` !!! warning "Stabilizer state expressions" - The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as `SProjector`, [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices. + The state written as $\frac{|Z₁⟩⊗|Z₁⟩+|Z₂⟩⊗|Z₂⟩}{√2}$ is a well known stabilizer state, namely a Bell state. However, automatically expressing it as a stabilizer is a prohibitively expensive computational operation in general. We do not perform that computation automatically. If you want to ensure that states you define can be automatically converted to tableaux for Clifford simulations, avoid using summation of kets. On the other hand, in all of our Clifford Monte-Carlo simulations, `⊗` is fully supported, as well as [`SProjector`](@ref), [`MixedState`](@ref), [`StabilizerState`](@ref), and summation of density matrices. From f603dfa07adeea205f39d85ef0c2a723e8f4c775 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 17:20:04 -0400 Subject: [PATCH 85/93] misc cleanup, adding TODOs, and renaming --- CHANGELOG.md | 2 +- docs/make.jl | 2 +- examples/repeatergrid/README.md | 19 +++++++++++++++++++ examples/repeatergrid/Readme.md | 5 ----- src/ProtocolZoo/ProtocolZoo.jl | 13 +++++++------ src/ProtocolZoo/cutoff.jl | 25 +++++++++++++++++-------- src/ProtocolZoo/swapping.jl | 6 +++--- src/queries.jl | 4 ++-- 8 files changed, 50 insertions(+), 26 deletions(-) create mode 100644 examples/repeatergrid/README.md delete mode 100644 examples/repeatergrid/Readme.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 68b3376..fb0f502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # News -## v0.5.0 - 2024-08-11 +## v0.5.0 - 2024-09-05 - Develop `CutoffProt` to deal with deadlocks in a simulation - Expand `SwapperProt` with `agelimit` to permit cutoff policies (with `CutoffProt`) diff --git a/docs/make.jl b/docs/make.jl index c40e133..22ef6f8 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -4,7 +4,7 @@ push!(LOAD_PATH,"../src/") using Documenter using DocumenterCitations using QuantumSavory -using QuantumSavory.ProtocolZoo +using QuantumSavory.ProtocolZoo # TODO is this the correct place to place this to ensure cross_references work DocMeta.setdocmeta!(QuantumSavory, :DocTestSetup, :(using QuantumSavory); recursive=true) diff --git a/examples/repeatergrid/README.md b/examples/repeatergrid/README.md new file mode 100644 index 0000000..3ff8f90 --- /dev/null +++ b/examples/repeatergrid/README.md @@ -0,0 +1,19 @@ +# Large Grid Network with Classical Synchronization of Messages and only "Local Knowledge" Control + +Our goal is to simply entangle two specific clients on a grid network. +All nodes of the network are capable of running nearest-neighbor entanglement generation, swaps, potentially cutoff-time deletion of old qubits, all of the classical communication machinery to distribute the necessary metadata among neighbors. + +This is very much a simple **local knowledge and NO global controller** setup for network control. + +This example visualizes a quantum network attempting to distribute between the Alice and Bob user pair located on the diagonal of a grid topology. +Asynchronous messaging and queries are used for classical communication of entanglement information between nodes using protocols like [`EntanglementTracker`](@ref) and [`SwapperProt`](@ref). +Link-level-entanglement is generated between all the horizontal and vertical neighbors using an entanglement generation protocol called [`EntanglerProt`](@ref). +As an entanglement link is established between the end users, it is consumed by a protocol named [`EntanglementConsumer`](@ref) which records the fidelity and time of consumption of the pair. +The qubits that remain unused beyond their `retention_time` are discarded by the [`CutoffProt`](@ref) + + +This module provides two ways of running the simulation: + +- [`SwapperProt`](@ref) and [`CutoffProt`](@ref) in an asynchronous manner where they run independently and all the classical information about the quantum states is reconciled using asynchronous messages sent to the tracker. + +- [`SwapperProt`](@ref) does not use qubits that are too old (and independently expected to be thrown away by the [`CutoffProt`](@ref)), by checking their `agelimit` parameter passed to it during initialization. Here, there are no outgoing messages from the [`CutoffProt`](@ref). \ No newline at end of file diff --git a/examples/repeatergrid/Readme.md b/examples/repeatergrid/Readme.md deleted file mode 100644 index 18a9574..0000000 --- a/examples/repeatergrid/Readme.md +++ /dev/null @@ -1,5 +0,0 @@ -This example visualizes a quantum network attempting to distribute between the Alice and Bob user pair located on the diagonal of a grid topology where asynchronous messaging and queries are used for classical communication of entanglement information between modes using protocols like [`EntanglementTracker`](@ref) and [`SwapperProt`](@ref). Link-level-entanglement is generated between all the horizontal and vertical neighbors using an entanglement generation protocol called [`EntanglerProt`](@ref). As an entanglement link is established between the end users, it is consumed by a protocol named [`EntanglementConsumer`](@ref) which records the fidelity and time of consumption of the pair. Also, the qubits that remain unused beyond their `retention_time` are discarded by the [`CutoffProt`](@ref) This module provides two ways of running the simulation using: - -- [`SwapperProt`](@ref) and [`CutoffProt`](@ref) in an asynchronous manner where they run independently and all the classical information about the quantum states is reconciled using asynchronous messages sent to the tracker. - -- [`SwapperProt`](@ref) does not use qubits that are to be thrown away by the [`CutoffProt`](@ref) by checking their `agelimit` parameter passed to it during initialization. Here, there are no outgoing messages from the [`CutoffProt`](@ref) and everything is handled by being synchronous. \ No newline at end of file diff --git a/src/ProtocolZoo/ProtocolZoo.jl b/src/ProtocolZoo/ProtocolZoo.jl index bf4275e..c661e51 100644 --- a/src/ProtocolZoo/ProtocolZoo.jl +++ b/src/ProtocolZoo/ProtocolZoo.jl @@ -124,21 +124,22 @@ Tag(tag::EntanglementUpdateZ) = Tag(EntanglementUpdateZ, tag.past_local_node, ta """ $TYPEDEF -This tag arrives as a message from a remote node's Cutoff Protocol to which the current node was entangled, to -update the classical metadata of the entangled slot and empty it. It is also stored at a node to handle incoming `EntanglementUpdate` and `EntanglementDelete` messages. +This tag arrives as a message from a remote node's Cutoff Protocol to which the current node was entangled, +to update the classical metadata of the entangled slot and empty it. +It is also stored at a node to handle incoming `EntanglementUpdate` and `EntanglementDelete` messages. $TYPEDFIELDS See also: [`CutoffProt`](@ref) """ @kwdef struct EntanglementDelete - "The node that sent the deletion message" + "the node that sent the deletion announcement message after they delete their local qubit" send_node::Int - "The sender's slot containing the decoherent qubit" + "the sender's slot containing the decohered qubit" send_slot::Int - "The node receiving the message for qubit deletion" + "the node receiving the message for qubit deletion" rec_node::Int - "The slot containing decoherent qubit" + "the slot containing decohered qubit" rec_slot::Int end Base.show(io::IO, tag::EntanglementDelete) = print(io, "Deleted $(tag.send_node).$(tag.send_slot) which was entangled to $(tag.rec_node).$(tag.rec_slot)") diff --git a/src/ProtocolZoo/cutoff.jl b/src/ProtocolZoo/cutoff.jl index 41ae080..664d127 100644 --- a/src/ProtocolZoo/cutoff.jl +++ b/src/ProtocolZoo/cutoff.jl @@ -6,6 +6,11 @@ checking periodically for any qubits in the node that have remained unused for more than the retention period of the qubit and emptying such slots. +If coordination messages are exchanged during deletions +(instances of the type [`EntanglementDelete`](@ref)), +then a [`EntanglementTracker`](@ref) protocol needs to also run, +to act on such messages. + $FIELDS """ @kwdef struct CutoffProt{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}} @@ -17,10 +22,10 @@ $FIELDS node::Int """time period between successive queries on the node (`nothing` for queuing up)""" period::LT = 0.1 - """Time after which a slot is emptied""" + """time after which a slot is emptied""" retention_time::Float64 = 5.0 - """No messages are sent when this is set to true""" - sync::Bool = false + """if `true`, synchronization messages are sent after a deletion to the node containing the other entangled qubit""" + announce::Bool = true end function CutoffProt(sim::Simulation, net::RegisterNet, node::Int; kwargs...) @@ -46,21 +51,25 @@ end traceout!(slot) msg = Tag(EntanglementDelete, prot.node, slot.idx, info.tag[2], info.tag[3]) tag!(slot, msg) - (prot.sync) || put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) + (prot.announce) && put!(channel(prot.net, prot.node=>msg[4]; permit_forward=true), msg) @debug "CutoffProt @$(prot.node): Send message to $(msg[4]) | message=`$msg` | time=$(now(prot.sim))" end - #delete old history tags - info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) + # TODO the tag deletions below are not necessary when announce=true and EntanglementTracker is running on other nodes. Verify the veracity of that statement, make tests for both cases, and document. + + # delete old history tags + info = query(slot, EntanglementHistory, ❓, ❓, ❓, ❓, ❓;filo=false) # TODO we should have a warning if `queryall` returns more than one result -- what does it even mean to have multiple history tags here if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time # TODO this should be part of the query interface, not using non-public implementation details untag!(slot, info.id) end - #delete old EntanglementDelete tags - info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) + # delete old EntanglementDelete tags + # TODO Why do we have separate entanglementhistory and entanglementupdate but we have only a single entanglementdelete that serves both roles? We should probably have both be pairs of tags, for consistency and ease of reasoning + info = query(slot, EntanglementDelete, prot.node, slot.idx , ❓, ❓) # TODO we should have a warning if `queryall` returns more than one result -- what does it even mean to have multiple delete tags here if !isnothing(info) && now(prot.sim) - reg.tag_info[info.id][3] > prot.retention_time # TODO this should be part of the query interface, not using non-public implementation details untag!(slot, info.id) end + unlock(slot) end @yield timeout(prot.sim, prot.period) diff --git a/src/ProtocolZoo/swapping.jl b/src/ProtocolZoo/swapping.jl index c3dcb47..fec23c8 100644 --- a/src/ProtocolZoo/swapping.jl +++ b/src/ProtocolZoo/swapping.jl @@ -7,11 +7,11 @@ function findswapablequbits(net, node, pred_low, pred_high, choose_low, choose_h reg = net[node] low_nodes = [ n for n in queryall(reg, EntanglementCounterpart, pred_low, ❓; locked=false, assigned=true) - if isnothing(agelimit) || !isolderthan(n.slot, agelimit) + if isnothing(agelimit) || !isolderthan(n.slot, agelimit) # TODO add age limit to query and queryall ] high_nodes = [ n for n in queryall(reg, EntanglementCounterpart, pred_high, ❓; locked=false, assigned=true) - if isnothing(agelimit) || !isolderthan(n.slot, agelimit) + if isnothing(agelimit) || !isolderthan(n.slot, agelimit) # TODO add age limit to query and queryall ] (isempty(low_nodes) || isempty(high_nodes)) && return nothing @@ -84,7 +84,7 @@ end 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) - + uptotime!((q1, q2), now(prot.sim)) swapcircuit = LocalEntanglementSwap() xmeas, zmeas = swapcircuit(q1, q2) diff --git a/src/queries.jl b/src/queries.jl index 55c3523..56aee96 100644 --- a/src/queries.jl +++ b/src/queries.jl @@ -418,11 +418,11 @@ function Base.showerror(io::IO, err::NotAssignedError) println("In function: $(err.f)") end -function isolderthan(slot::RegRef, time_left::Float64) +function isolderthan(slot::RegRef, age::Float64) if !isassigned(slot) throw(NotAssignedError("Slot must be assigned with a quantum state before checking coherence.", isolderthan)) end id = query(slot, QuantumSavory.ProtocolZoo.EntanglementCounterpart, ❓, ❓).id slot_time = slot.reg.tag_info[id][3] - return (now(get_time_tracker(slot))) - slot_time > time_left + return (now(get_time_tracker(slot))) - slot_time > age end From 5d8d0ddd09bfb8a3a66a0d74e9d7f55b7e562bfa Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 20:55:45 -0400 Subject: [PATCH 86/93] cleanup of the example files --- examples/repeatergrid/1a_async_interactive_visualization.jl | 4 ++-- examples/repeatergrid/1b_async_wglmakie_interactive.jl | 4 ++-- examples/repeatergrid/2a_sync_interactive_visualization.jl | 6 +++--- examples/repeatergrid/2b_sync_wglmakie_interactive.jl | 6 +++--- examples/repeatergrid/setup.jl | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index 00317cc..dbacd33 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -36,7 +36,7 @@ lines!(num_epr_axis, num_epr_info) # sliders sg = SliderGrid( # TODO significant code duplication with the other examples - fig[4,1], + fig[4,:], (label="Probability of success of Entanglement generation at each attempt", range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", @@ -68,7 +68,7 @@ step_ts = range(0, 1000, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) ylims!(fid_axis, (0, 1.04)) diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl index 7fe2ab1..d8dfcf3 100644 --- a/examples/repeatergrid/1b_async_wglmakie_interactive.jl +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -42,7 +42,7 @@ function prepare_singlerun() # sliders sg = SliderGrid( # TODO significant code duplication with the other examples - fig[3,1], + fig[4,:], (label="Probability of success of Entanglement generation at each attempt", range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", @@ -77,7 +77,7 @@ function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, run for t in step_ts run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) ylims!(fid_axis, (0, 1.04)) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index 1f5adeb..c906655 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -3,7 +3,7 @@ using GLMakie include("setup.jl") -sim, net, graph, consumer, params... = prepare_simulation(;sync=true) +sim, net, graph, consumer, params... = prepare_simulation(;announce=false) fig = Figure(;size=(1200, 1100)) @@ -35,7 +35,7 @@ lines!(num_epr_axis, num_epr_info) # sliders sg = SliderGrid( # TODO significant code duplication with the other examples - fig[3,1], + fig[4,:], (label="Probability of success of Entanglement generation at each attempt", range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", @@ -67,7 +67,7 @@ step_ts = range(0, 1000, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) ylims!(fid_axis, (0, 1.04)) diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl index 5691173..0b9f959 100644 --- a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -10,7 +10,7 @@ const custom_css = Bonito.DOM.style("ul {list-style: circle !important;}") # TOD function prepare_singlerun() # Prepare all of the simulation components (while all visualization components are prepared in the rest of this function) - sim, net, graph, consumer, params... = prepare_simulation(;sync=true) + sim, net, graph, consumer, params... = prepare_simulation(;announce=false) # Prepare the main figure fig = Figure(;size=(1200, 1100)) @@ -42,7 +42,7 @@ function prepare_singlerun() # sliders sg = SliderGrid( - fig[3,1], + fig[4,:], (label="Probability of success of Entanglement generation at each attempt", range=0.001:0.05:1.0, format="{:.3f}", startvalue=0.001), (label="Local busy time for swapper", @@ -77,7 +77,7 @@ function continue_singlerun!(sim, obs, entlog, params, entlogaxis, histaxis, run for t in step_ts run(sim, t) notify.((obs,entlog)) - notify.(params) + notify.(params) ylims!(entlogaxis, (-1.04,1.04)) xlims!(entlogaxis, max(0,t-50), 1+t) ylims!(fid_axis, (0, 1.04)) diff --git a/examples/repeatergrid/setup.jl b/examples/repeatergrid/setup.jl index a44c2cb..fd083b0 100644 --- a/examples/repeatergrid/setup.jl +++ b/examples/repeatergrid/setup.jl @@ -36,7 +36,7 @@ end # Simulation setup -function prepare_simulation(;sync=false) +function prepare_simulation(;announce=true) n = 6 # number of nodes on each row and column for a 6x6 grid regsize = 20 # memory slots in each node @@ -72,7 +72,7 @@ function prepare_simulation(;sync=false) chooseL = cL, chooseH = cH, rounds=-1, local_busy_time=local_busy_time[], retry_lock_time=retry_lock_time[], - agelimit=sync ? retention_time[]-buffer_time[] : nothing) + agelimit=announce ? nothing : retention_time[]-buffer_time[]) @process swapper() end @@ -90,7 +90,7 @@ function prepare_simulation(;sync=false) # decoherence protocol runs at each node to free up slots that haven't been used past the retention time period_dec = Observable(0.1) for v in vertices(net) - decprot = CutoffProt(sim, net, v; sync=sync, period=period_dec[]) # TODO default and slider for retention_time + decprot = CutoffProt(sim, net, v; announce, period=period_dec[]) # TODO default and slider for retention_time @process decprot() end From edebdbe844f88815de99dc044e66d74eeb78c4d7 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 21:06:12 -0400 Subject: [PATCH 87/93] minor subjective stylistic changes to doc file --- docs/src/howto/repeatergrid/repeatergrid.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/src/howto/repeatergrid/repeatergrid.md b/docs/src/howto/repeatergrid/repeatergrid.md index d561058..5f96d90 100644 --- a/docs/src/howto/repeatergrid/repeatergrid.md +++ b/docs/src/howto/repeatergrid/repeatergrid.md @@ -7,6 +7,9 @@ end ``` This section provides a detailed walkthrough of how QuantumSavory.jl can be used to simulate entanglement generation on a network of repeaters where each repeater relies only on local knowledge of the network. +This is only one of many ways in which such a network can be set up, focusing on one particular "no global knowledge" approach. + +A complete implementation of the simulation described here is available in the `examples/repeatergrid` folder of the `QuantumSavory` repository. For this example, we consider a square grid topology in which each node is connected to its nearest neighbors. The registers act as repeater nodes. The nodes on the diagonal corners are Alice and Bob, the two special nodes that the network is trying to entangle through generating link-level entanglement at each edge and performing appropriate swaps at each node. @@ -15,11 +18,11 @@ The goal is to establish entanglement between Alice and Bob by routing entanglem This employs functionality from the `ProtocolZoo` module of QuantumSavory to run the following Quantum Networking protocols: -- [`EntanglerProt`](@ref): Entangler protocol to produce link level entanglement at each edge in the network +- [`EntanglerProt`](@ref): Entangler protocol to produce link-level entanglement at each edge in the network - [`SwapperProt`](@ref): Swapper protocol runs at each node except at the Alice and Bob nodes, to perform swaps. The swaps are performed only if a query deems them useful for propagating entanglement closer and closer to Alice and Bob. -- [`EntanglementTracker`](@ref): Entanglement Tracker protocol to keep track of/and update the local link state-classical knowledge by querying for "entanglement update" messages generated by the other protocols (`SwapperProt` & `CutoffProt` specifically). +- [`EntanglementTracker`](@ref): Entanglement Tracker protocol to keep track of and update the local link state (classical knowledge) by listening for "entanglement update" messages generated by the other protocols (`SwapperProt` & `CutoffProt` specifically). - [`CutoffProt`](@ref): As the simulation progresses, the unused entangled pairs generated by `EntanglerProt` need to be discarded due to the loss of fidelity under noise as they might not be suitable for networking applications beyond a certain cutoff interval of time from their instantiation. The `CutoffProt` is instantiated with a `retention_time` parameter that discards such qubits in each node. @@ -27,7 +30,7 @@ This employs functionality from the `ProtocolZoo` module of QuantumSavory to run All of the above protocols rely on the query and tagging functionality as described in the [Tagging and Querying](@ref tagging-and-querying) section. -Other than that, `ConcurrentSim` and `ResumableFunctions` are used in the backend to run the discrete event simulation. `Graphs` helps with some functionality needed for `RegisterNet` datastructure that forms the grid. `GLMakie` and `NetworkLayout` are used for visualization along with the visualization functionality implemented in `QuantumSavory` itself. +Other than that, `ConcurrentSim` and `ResumableFunctions` are used in the backend to run the discrete event simulation. `Graphs` helps with some functionality needed for the `RegisterNet` datastructure that forms the grid. `GLMakie` and `NetworkLayout` are used for visualization along with the visualization functionality implemented in `QuantumSavory` itself. # Custom Predicate And Choosing function @@ -122,7 +125,10 @@ end ``` We set up the simulation to run with a 6x6 grid of nodes above. Here, each node has 8 qubit slots. -Each vertical and horizontal edge runs an entanglement generation protocol. Each node in the network runs an entanglement tracker protocol and all of the nodes except the nodes that we're trying to connect, i.e., Alice' and Bob's nodes which are at the diagonal ends of the grid run the swapper protocol. The code that runs and visualizes this simulation is shown below +Each vertical and horizontal edge runs an entanglement generation protocol. +Each node in the network runs an entanglement tracker protocol and all of the nodes except the nodes that we're trying to connect, +i.e., Alice's and Bob's nodes which are at the diagonal ends of the grid run the swapper protocol. +The code that runs and visualizes this simulation is shown below ```julia fig = Figure(;size=(600, 600)) From 1ab540b9f01d7a1adc1ea147bbf4011ef38334e7 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 22:00:00 -0400 Subject: [PATCH 88/93] doc fix --- src/ProtocolZoo/cutoff.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ProtocolZoo/cutoff.jl b/src/ProtocolZoo/cutoff.jl index 664d127..da17356 100644 --- a/src/ProtocolZoo/cutoff.jl +++ b/src/ProtocolZoo/cutoff.jl @@ -7,7 +7,7 @@ have remained unused for more than the retention period of the qubit and emptying such slots. If coordination messages are exchanged during deletions -(instances of the type [`EntanglementDelete`](@ref)), +(instances of the type `EntanglementDelete`), then a [`EntanglementTracker`](@ref) protocol needs to also run, to act on such messages. From 892651e045f4d689cc1455d3de0f72aac7a9a2e0 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 22:00:26 -0400 Subject: [PATCH 89/93] shorten the repeatergrid demos, they take much too long during tests --- examples/repeatergrid/1a_async_interactive_visualization.jl | 2 +- examples/repeatergrid/2a_sync_interactive_visualization.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index dbacd33..c46a2c5 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -64,7 +64,7 @@ end display(fig) -step_ts = range(0, 1000, step=0.1) +step_ts = range(0, 100, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index c906655..70b08ee 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -63,7 +63,7 @@ end display(fig) -step_ts = range(0, 1000, step=0.1) +step_ts = range(0, 100, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) From b56c53ec67331064ace2ee682edeff8774ae0191 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 22:02:04 -0400 Subject: [PATCH 90/93] env variable name fixup for repeatergrid example --- examples/repeatergrid/1b_async_wglmakie_interactive.jl | 6 +++--- examples/repeatergrid/2b_sync_wglmakie_interactive.jl | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/repeatergrid/1b_async_wglmakie_interactive.jl b/examples/repeatergrid/1b_async_wglmakie_interactive.jl index d8dfcf3..bf99166 100644 --- a/examples/repeatergrid/1b_async_wglmakie_interactive.jl +++ b/examples/repeatergrid/1b_async_wglmakie_interactive.jl @@ -143,9 +143,9 @@ end; # Serve the Makie app isdefined(Main, :server) && close(server); -port = parse(Int, get(ENV, "ASYNC_GRID_PORT", "8888")) -interface = get(ENV, "ASYNC_GRID_IP", "127.0.0.1") -proxy_url = get(ENV, "ASYNC_GRID_PROXY", "") +port = parse(Int, get(ENV, "QS_ASYNC_REPEATERGRID_PORT", "8888")) +interface = get(ENV, "QS_ASYNC_REPEATERGRID_IP", "127.0.0.1") +proxy_url = get(ENV, "QS_ASYNC_REPEATERGRID_PROXY", "") server = Bonito.Server(interface, port; proxy_url); Bonito.HTTPServer.start(server) Bonito.route!(server, "/" => landing); diff --git a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl index 0b9f959..f79ef37 100644 --- a/examples/repeatergrid/2b_sync_wglmakie_interactive.jl +++ b/examples/repeatergrid/2b_sync_wglmakie_interactive.jl @@ -142,9 +142,9 @@ end; # Serve the Makie app isdefined(Main, :server) && close(server); -port = parse(Int, get(ENV, "SYNC_GRID_PORT", "8888")) -interface = get(ENV, "SYNC_GRID_IP", "127.0.0.1") -proxy_url = get(ENV, "SYNC_GRID_PROXY", "") +port = parse(Int, get(ENV, "QS_SYNC_REPEATERGRID_PORT", "8888")) +interface = get(ENV, "QS_SYNC_REPEATERGRID_IP", "127.0.0.1") +proxy_url = get(ENV, "QS_SYNC_REPEATERGRID_PROXY", "") server = Bonito.Server(interface, port; proxy_url); Bonito.HTTPServer.start(server) Bonito.route!(server, "/" => landing); From fabc5eba875b37d0892b0e2071b05a569b399195 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 22:03:01 -0400 Subject: [PATCH 91/93] shorten repeatergrid demos even more --- examples/repeatergrid/1a_async_interactive_visualization.jl | 2 +- examples/repeatergrid/2a_sync_interactive_visualization.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/repeatergrid/1a_async_interactive_visualization.jl b/examples/repeatergrid/1a_async_interactive_visualization.jl index c46a2c5..821382d 100644 --- a/examples/repeatergrid/1a_async_interactive_visualization.jl +++ b/examples/repeatergrid/1a_async_interactive_visualization.jl @@ -64,7 +64,7 @@ end display(fig) -step_ts = range(0, 100, step=0.1) +step_ts = range(0, 50, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) diff --git a/examples/repeatergrid/2a_sync_interactive_visualization.jl b/examples/repeatergrid/2a_sync_interactive_visualization.jl index 70b08ee..276335a 100644 --- a/examples/repeatergrid/2a_sync_interactive_visualization.jl +++ b/examples/repeatergrid/2a_sync_interactive_visualization.jl @@ -63,7 +63,7 @@ end display(fig) -step_ts = range(0, 100, step=0.1) +step_ts = range(0, 50, step=0.1) record(fig, "grid_sim6x6hv.mp4", step_ts; framerate=10, visible=true) do t run(sim, t) notify.((obs,entlog)) From 3b273d8a7cf1afc48fc881bbc4da86421c2dc954 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 5 Sep 2024 22:26:43 -0400 Subject: [PATCH 92/93] fix the freakin doc building failure... gosh this was staring us in the face for so long --- ext/QuantumSavoryMakie/QuantumSavoryMakie.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl b/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl index 5f0740e..799eca7 100644 --- a/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl +++ b/ext/QuantumSavoryMakie/QuantumSavoryMakie.jl @@ -264,15 +264,15 @@ function Makie.process_interaction(handler::RNHandler, event::Makie.MouseEvent, #else if plot===rn[:register_slots_scatterplot][] register, registeridx, slot = rn[:register_slots_coords_backref][][index] - run(`clear`) + try run(`clear`) catch end println("Register $registeridx | Slot $(slot)\n Details: $(register)") elseif plot===rn[:state_scatterplot][] state, reg, registeridx, slot, subsystem = rn[:state_coords_backref][][index] - run(`clear`) + try run(`clear`) catch end println("Subsystem stored in Register $(registeridx) | Slot $(slot)\n Subsystem $(subsystem) of $(state)") elseif plot===rn[:observables_scatterplot][] o, val = rn[:observables_backref][][index] - run(`clear`) + try run(`clear`) catch end println("Observable $(o) has value $(val)") end false From a56e783fc28298183ea52c4268f0210d5113ae18 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 6 Sep 2024 09:44:45 -0400 Subject: [PATCH 93/93] make autolims in examples/congestionchain more resilient --- examples/congestionchain/1_visualization.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/examples/congestionchain/1_visualization.jl b/examples/congestionchain/1_visualization.jl index 5ac764e..c1df5d8 100644 --- a/examples/congestionchain/1_visualization.jl +++ b/examples/congestionchain/1_visualization.jl @@ -49,10 +49,12 @@ step_ts = range(0, 1000, step=0.1) record(fig, "congestionchain.mp4", step_ts; framerate=50, visible=true) do t run(sim, t) ax.title = "t=$(t)" - notify(obs) - notify(ts) - autolimits!(ax_fidXX) - autolimits!(ax_fidZZ) + if length(ts[])>2 # to avoid failing autolimits on empty plots + notify(obs) + notify(ts) + autolimits!(ax_fidXX) + autolimits!(ax_fidZZ) + end end ##