From 27400bf7e731903e58661b1ac0a6e1e2f8dcd848 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Fri, 17 Nov 2023 00:25:13 -0500 Subject: [PATCH] initial queries and tags setup --- Project.toml | 2 ++ src/QuantumSavory.jl | 10 +++++++- src/queries.jl | 59 ++++++++++++++++++++++++++++++++++++++++++++ src/tags.jl | 18 ++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/queries.jl create mode 100644 src/tags.jl diff --git a/Project.toml b/Project.toml index 8d2aad0..fdfd445 100644 --- a/Project.toml +++ b/Project.toml @@ -4,6 +4,7 @@ authors = ["Stefan Krastanov "] version = "0.3.2" [deps] +Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" ConcurrentSim = "6ed1e86c-fcaf-46a9-97e0-2b26a2cdb499" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" @@ -21,6 +22,7 @@ QuantumSymbolics = "efa7fd63-0460-4890-beb7-be1bbdfbaeae" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" ResumableFunctions = "c5292f4c-5179-55e1-98c5-05642aab7184" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +SumTypes = "8e1ec7a9-0e02-4297-b0fe-6433085c89f2" [weakdeps] Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" diff --git a/src/QuantumSavory.jl b/src/QuantumSavory.jl index 977265d..b48fe54 100644 --- a/src/QuantumSavory.jl +++ b/src/QuantumSavory.jl @@ -16,6 +16,9 @@ export project_traceout! #TODO should move to QuantumInterface import ConcurrentSim using ResumableFunctions +import SumTypes: @sum_type +import Combinatorics: powerset + @reexport using QuantumSymbolics using QuantumSymbolics: AbstractRepresentation, AbstractUse, @@ -31,6 +34,7 @@ export Qubit, Qumode, QuantumStateTrait, UseAsState, UseAsObservable, UseAsOperation, AbstractBackground export QuantumChannel +export tag!, tag_types #TODO you can not assume you can always in-place modify a state. Have all these functions work on stateref, not stateref[] @@ -51,6 +55,7 @@ struct Qumode <: QuantumStateTrait end default_repr(::Qubit) = QuantumOpticsRepr() default_repr(::Qumode) = QuantumOpticsRepr() +include("tags.jl") # TODO better constructors # TODO am I overusing Ref @@ -75,6 +80,7 @@ mutable struct Register # TODO better type description accesstimes::Vector{Float64} # TODO do not hardcode the type env::Any locks::Vector{Any} + tags::Vector{Set{Tag}} end Register(traits,reprs,bg,sr,si) = Register(traits,reprs,bg,sr,si,fill(0.0,length(traits))) Register(traits,reprs,bg) = Register(traits,reprs,bg,fill(nothing,length(traits)),fill(0,length(traits)),fill(0.0,length(traits))) @@ -86,7 +92,7 @@ Register(nqubits::Int,repr::AbstractRepresentation) = Register(fill(Qubit(),nqub Register(nqubits::Int,bg::AbstractBackground) = Register(fill(Qubit(),nqubits),fill(bg,nqubits)) function Register(traits, reprs, bg, sr, si, at) env = ConcurrentSim.Simulation() - Register(traits, reprs, bg, sr, si, at, env, [ConcurrentSim.Resource(env) for _ in traits]) + Register(traits, reprs, bg, sr, si, at, env, [ConcurrentSim.Resource(env) for _ in traits], [Set{Tag}() for _ in traits]) end """ @@ -323,6 +329,8 @@ include("baseops/apply.jl") include("baseops/uptotime.jl") include("baseops/observable.jl") +include("queries.jl") + include("representations.jl") include("backgrounds.jl") include("noninstant.jl") diff --git a/src/queries.jl b/src/queries.jl new file mode 100644 index 0000000..19711e2 --- /dev/null +++ b/src/queries.jl @@ -0,0 +1,59 @@ +function tag!(ref::RegRef, tag::Tag) + push!(ref.reg.tags[ref.idx], tag) +end + +"""Wildcard for use with the tag querying functionality. + +See also: [`query`](@ref), [`tag!`](@ref), [`tag_types`](@ref)""" +struct Wildcard end + +"""A wilcard instance for use with the tag querying functionality. + +See also: [`query`](@ref), [`tag!`](@ref), [`tag_types`](@ref)""" +const W = Wildcard() +const ❓ + +function query(reg::Register, tag::Tag) + i = findfirst(set -> tag ∈ set, reg.tags) + isnothing(i) ? nothing : (reg.refs[i], tag) +end + +_query_and() = true +_query_and(a::Bool) = a +_query_and(a::Bool, b::Bool) = a && b + +# 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)[1:length(sig)] + argssig = [:($a::$t) for (a,t) in zip(args, sig)] + + eval(quote function tag!(ref::RegRef, $(argssig...)) + tag!(ref, ($tagvariant)($(args...))) + end end) + + eval(quote function query(reg::Register, $(argssig...)) + query(reg, ($tagvariant)($(args...))) + 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(int_idx_all, idx)...) + sig_wild = collect(sig) + sig_wild[idx] .= Wildcard + argssig_wild = [:($a::$t) for (a,t) in zip(args, sig_wild)] + nonwild_checks = [:(tag.data[i]==$(args[i])) for i in complement_idx] + eval(quote function query(reg::Register, $(argssig_wild...)) + for (reg_idx, tags) in enumerate(reg.tags) + for tag in tags + if isvariant(tag, $(tagsymbol)) + if _query_all($(nonwild_checks...)) end + return (reg_idx, tag) + end + end + end + end end) + end + +end diff --git a/src/tags.jl b/src/tags.jl new file mode 100644 index 0000000..8151d5e --- /dev/null +++ b/src/tags.jl @@ -0,0 +1,18 @@ +export tags + +@sum_type Tag :hidden begin + Symbol(::Symbol) + SymbolInt(::Symbol, ::Int) + SymbolIntInt(::Symbol, ::Int, ::Int) + Type(::DataType) + TypeInt(::DataType, ::Int) + TypeIntInt(::DataType, ::Int, ::Int) + TypeSymbol(::DataType, ::Symbol) + TypeSymbolInt(::DataType, ::Symbol, ::Int) + TypeSymbolIntInt(::DataType, ::Symbol, ::Int, ::Int) +end + +"""Tag types available in the taggging and tag-querying system. + +See also: [`query`](@ref), [`tag!`](@ref), [`Wildcard`](@ref)""" +const tag_types = Tag'