Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added Query Interface and some doc fixes #92

Merged
merged 16 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ Random = "1"
Reexport = "1.2.2"
ResumableFunctions = "0.6"
Statistics = "1"
SumTypes = "0.5.1"
SumTypes = "0.5.5"
julia = "1.9"
8 changes: 4 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function main()
plugins = [bib],
doctest = false,
clean = true,
warnonly = true, # TODO [:missing_docs],
warnonly = [:missing_docs],
sitename = "QuantumSavory.jl",
format = Documenter.HTML(
assets=["assets/init.js"]
Expand All @@ -25,12 +25,11 @@ function main()
"Getting Started Manual" => "manual.md",
"Explanations" => [
"explanations.md",
"Register Interface" => "register_interface.md",
"Properties and Backgrounds" => "propbackgrounds.md",
"Symbolic Expressions" => "symbolics.md",
"Tagging and Querying" => "tag_query.md",
"Visualizations" => "visualizations.md",
"Dev Documentation" => [
"Register Interface" => "register_interface.md",
],
],
"How-To Guides" => [
"howto.md",
Expand All @@ -49,6 +48,7 @@ function main()
"API" => "API.md",
"CircuitZoo API" => "API_CircuitZoo.md",
"StatesZoo API" => "API_StatesZoo.md",
"ProtocolZoo API" => "API_ProtocolZoo.md",
"Bibliography" => "bibliography.md",
],
]
Expand Down
26 changes: 26 additions & 0 deletions docs/src/API_ProtocolZoo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Available Protocols

```@raw html
<style>
.content table td {
padding-top: 0 !important;
padding-bottom: 0 !important;
}
</style>
```

## Autogenerated API list for `QuantumSavory.ProtocolZoo`

```@autodocs
Modules = [QuantumSavory.ProtocolZoo]
Private = false
```

## Non-exported custom tags used by these protocols

```@docs
QuantumSavory.ProtocolZoo.EntanglementCounterpart
QuantumSavory.ProtocolZoo.EntanglementHistory
QuantumSavory.ProtocolZoo.EntanglementUpdateX
QuantumSavory.ProtocolZoo.EntanglementUpdateZ
```
1 change: 1 addition & 0 deletions docs/src/explanations.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ You probably want to cover the:
- `Register` and `RegisterNet` structures
- basic interface used by the library
- symbolic capabilities for formalism-agnostic description
- metadata tagging and metadata queries for interoperability between protocols
- available simulator backends
- discrete event simulations and time-tracking capabilities
- background noise processes
Expand Down
2 changes: 1 addition & 1 deletion docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ @article{keisuke2009doubleselection
journal={Phys. Rev. A 80, 042308},
year={2009},
url={https://doi.org/10.1103/PhysRevA.80.042308},
doi={https://doi.org/10.1103/PhysRevA.80.042308}
doi={10.1103/PhysRevA.80.042308}
}

@article{krastanov2019optimised,
Expand Down
24 changes: 24 additions & 0 deletions docs/src/register_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ A rather diverse set of simulation libraries is used under the hood. Long term t

Initialize the state of a register to a known state.

```@docs; canonical=false
initialize!
```

#### `initialize!(refs::Vector{RegRef}, state; time)`

Store a `state` in the given register slots.
Expand Down Expand Up @@ -66,6 +70,10 @@ flowchart TB

Apply a quantum operation to a register.

```@docs; canonical=false
apply!
```

#### `apply!(refs::Vector{RegRef}, operation; time)`

Applying an `operation` to the qubits referred to by the sequence of [`RegRef`](@ref)s at a specified `time`.
Expand Down Expand Up @@ -126,6 +134,10 @@ flowchart TB

Measure a quantum observable. The dispatch down the call three is very similar to the one for `apply!`.

```@docs; canonical=false
observable
```

#### `observable(refs::Tuple{Vararg{RegRef, N}}, obs, something=nothing; time)`

Calculate the value of an observable on the state in the sequence of [`RegRef`](@ref)s at a specified `time`. If these registers are not instantiated, return `something`.
Expand Down Expand Up @@ -180,6 +192,10 @@ flowchart TB

## `project_traceout!`

```@docs; canonical=false
project_traceout!
```

#### `project_traceout!(r::RegRef, basis; time)`

Project the state in `RegRef` on `basis` at a specified `time`. `basis` can be a `Vector` or `Tuple` of basis states, or it can be a `Matrix` like `Z` or `X`.
Expand Down Expand Up @@ -228,6 +244,10 @@ flowchart TB

## `traceout!`

```@docs; canonical=false
traceout!
```

Perform a partial trace over a part of the system (i.e. discard a part of the system).

#### `traceout!(r::RegRef)`
Expand Down Expand Up @@ -257,6 +277,10 @@ flowchart TB

## `uptotime!`

```@docs; canonical=false
uptotime!
```

#### `uptotime!(ref::RegRef, now)`

Evolve the state in a `RegRef` upto a given time `now`
Expand Down
75 changes: 75 additions & 0 deletions docs/src/tag_query.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Tagging and Querying

```@meta
DocTestSetup = quote
using QuantumSavory
end
```

The [`query`](@ref) and [`tag!`](@ref) interface lets you manage "classical state" metadata in your simulations. In particular, this interface enables the creation of modular interoperable [control protocols](@ref "Available Protocols"). Each protocol can operate independently of others without knowledge of each others' internals. This is done by using various "tags" to communicate metadata between the network nodes running the protocols, and by the protocols querying for the presence of such tags, leading to greater flexibility when setting up different simulations.

The components of the query interface which make this possible are described below.

## The `Tag` type

```@docs; canonical=false
QuantumSavory.Tag
```

And here are all currently supported tag signatures:

```@example
using QuantumSavory #hide
[tuple(m.sig.types[2:end]...) for m in methods(Tag) if m.sig.types[2] ∈ (Symbol, DataType)]
```

## Assigning and removing tags

```@docs; canonical=false
QuantumSavory.tag!
QuantumSavory.untag!
```

## Querying for the pressence of a tag

The [`query`](@ref) function allows the user to query for [`Tag`](@ref)s in three different cases:
- on a particular qubit slot ([`RegRef`](@ref)) in a [`Register`](@ref) node;
- on a [`Register`](@ref) to query for any slot that contains the passed `Tag`;
- on a [`messagebuffer`](@ref) to query for a particular `Tag` received from another node in a network.

The `Tag` description passed to `query` can include predicate functions (of the form `x -> pass::Bool`) and wildcards (the [`❓`](@ref) variable), for situations where we have freedom in what tag we are exactly searching for.

The queries can search in `FIFO` or `FILO` order (`FILO` by default). E.g., for the default `FILO`, a query on a [`RegRef`](@ref) returns the `Tag` which is at the end of the vector of tags stored the given slot (as new tags are appended at the end). On a [`Register`](@ref) it returns the slot with the "youngest" age.

One can also query by "lock" and "assignment" status of a given slot, by using the `locked` and `assigned` boolean keywords. By default these keywords are set to `nothing` and these properties are not checked.

Following is a detailed description of each `query` methods

```@docs; canonical=false
query(::Register,::Tag)
query(::RegRef,::Tag)
query(::MessageBuffer,::Tag)
```

### Wildcards

```@docs; canonical=false
W
```

### `querydelete!`

A method on top of [`query`](@ref), which allows to query for tag in a [`RegRef`](@ref) or a [`messagebuffer`](@ref), returning the tag that satisfies the passed predicates and wildcars, **and deleting it from the list at the same time**. It otherwise has the same signature as [`query`](@ref).

```@docs; canonical=false
querydelete!(::RegRef)
querydelete!(::MessageBuffer)
```

### `queryall`
A method defined on top of [`query`](@ref) which allows to query for **all tags** in a [`RegRef`](@ref) or a [`Register`](@ref) that match the query.

```@docs; canonical=false
QuantumSavory.queryall
```
16 changes: 8 additions & 8 deletions docs/src/tutorial/message_queues.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,22 @@ time_before_success = now(sim)

## Communication delay

Classical communication delay might be important too. There are FILO storage stacks that can simulate that, e.g. `DelayChannel(sim, delay_time)` used instead of `Storage(sim)`. Below we augment the example from above with such a delay channel and we also add some crude instrumentation and plotting.
Classical communication delay might be important too. There are FILO storage stacks that can simulate that, e.g. `DelayQueue(sim, delay_time)` used instead of `Storage(sim)`. Below we augment the example from above with such a delay channel and we also add some crude instrumentation and plotting.

```@example messagechannel
sim = Simulation()
communication_delay = 1.0
channel_1to2 = DelayChannel{Bool}(sim, communication_delay)
channel_2to1 = DelayChannel{Bool}(sim, communication_delay)
channel_ready = DelayChannel{Bool}(sim, communication_delay)
channel_1to2 = DelayQueue{Bool}(sim, communication_delay)
channel_2to1 = DelayQueue{Bool}(sim, communication_delay)
channel_ready = DelayQueue{Bool}(sim, communication_delay)

global_log = []

@resumable function do_random_measurement_transmit_receive_compare(sim, channel_out, channel_in)
@yield timeout(sim, 2+rand()) # wait for the measurement to take place
local_measurement = rand() < 0.4 # simulate a random measurement result
put(channel_out, local_measurement)
other_measurement = @yield get(channel_in)
put!(channel_out, local_measurement)
other_measurement = @yield take!(channel_in)
succeeded = local_measurement == other_measurement == true
return succeeded
end
Expand All @@ -156,7 +156,7 @@ end
s = now(sim)
reset_duration = 2.0
@yield timeout(sim, reset_duration)
put(channel_ready, true)
put!(channel_ready, true)
push!(global_log, (:reset_system, s, now(sim)))
end

Expand All @@ -183,7 +183,7 @@ end
end
push!(global_log, (:node_2_meas_tx_rx, s, now(sim)))
s2 = now(sim)
@yield get(channel_ready)
@yield take!(channel_ready)
push!(global_log, (:node_2_wait_for_reset, s2, now(sim)))
end
end
Expand Down
60 changes: 57 additions & 3 deletions src/ProtocolZoo/ProtocolZoo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,40 +22,94 @@ get_time_tracker(prot::AbstractProtocol) = prot.sim

Process(prot::AbstractProtocol, args...; kwargs...) = Process((e,a...;k...)->prot(a...;k...,_prot=prot), get_time_tracker(prot), args...; kwargs...)

"""
$TYPEDEF

Indicates the current entanglement status with a remote node's slot. Added when a new entanglement is generated through [`EntanglerProt`](@ref) or when a swap happens and
the [`EntanglementTracker`](@ref) receives an [`EntanglementUpdate`] message.

$TYPEDFIELDS
"""
@kwdef struct EntanglementCounterpart
"the id of the remote node to which we are entangled"
remote_node::Int
"the slot in the remote node containing the qubit we are entangled to"
remote_slot::Int
end
Base.show(io::IO, tag::EntanglementCounterpart) = print(io, "Entangled to $(tag.remote_node).$(tag.remote_slot)")
Tag(tag::EntanglementCounterpart) = Tag(EntanglementCounterpart, tag.remote_node, tag.remote_slot)

"""
$TYPEDEF

This tag is used to store the outdated entanglement information after a
swap. It helps to direct incoming entanglement update messages to the right node after a swap.
It helps in situations when locally we have performed a swap, but we are now receiving a message
from a distant node that does not know yet that the swap has occurred (thus the distant node might
have outdated information about who is entangled to whom and we need to update that information).

$TYPEDFIELDS
"""
@kwdef struct EntanglementHistory
"the id of the remote node we used to be entangled to"
remote_node::Int
"the slot of the remote node we used to be entangled to"
remote_slot::Int
"the id of remote node to which we are entangled after the swap"
swap_remote_node::Int
"the slot of the remote node to which we are entangled after the swap"
swap_remote_slot::Int
"the slot in this register with whom we performed a swap"
swapped_local::Int
end
Base.show(io::IO, tag::EntanglementHistory) = print(io, "Was entangled to $(tag.remote_node).$(tag.remote_slot), but swapped with .$(tag.swapped_local) which was entangled to $(tag.swap_remote_node).$(tag.swap_remote_slot)")
Tag(tag::EntanglementHistory) = Tag(EntanglementHistory, tag.remote_node, tag.remote_slot, tag.swap_remote_node, tag.swap_remote_slot, tag.swapped_local)

"""
$TYPEDEF

This tag arrives as a message from a remote node to which the current node was entangled to update the
entanglement information and apply an `X` correction after the remote node performs an entanglement swap.

$TYPEDFIELDS
"""
@kwdef struct EntanglementUpdateX
"the id of the node to which you were entangled before the swap"
past_local_node::Int
"the slot of the node to which you were entangled before the swap"
past_local_slot::Int
"the slot of your node that we were entangled to"
past_remote_slot::Int
"the id of the node to which you are now entangled after the swap"
new_remote_node::Int
"the slot of the node to which you are now entangled after the swap"
new_remote_slot::Int
"what Pauli correction you need to perform"
correction::Int
end
Base.show(io::IO, tag::EntanglementUpdateX) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction Z$(tag.correction)")
Tag(tag::EntanglementUpdateX) = Tag(EntanglementUpdateX, tag.past_local_node, tag.past_local_slot, tag.past_remote_slot, tag.new_remote_node, tag.new_remote_slot, tag.correction)

"""
$TYPEDEF

This tag arrives as a message from a remote node to which the current node was entangled to update the
entanglement information and apply a `Z` correction after the remote node performs an entanglement swap.

$TYPEDFIELDS
"""
@kwdef struct EntanglementUpdateZ
"the id of the node to which you were entangled before the swap"
past_local_node::Int
"the slot of the node to which you were entangled before the swap"
past_local_slot::Int
"the slot of your node that we were entangled to"
past_remote_slot::Int
"the id of the node to which you are now entangled after the swap"
new_remote_node::Int
"the slot of the node to which you are now entangled after the swap"
new_remote_slot::Int
"what Pauli correction you need to perform"
correction::Int
end
Base.show(io::IO, tag::EntanglementUpdateZ) = print(io, "Update slot .$(tag.past_remote_slot) which used to be entangled to $(tag.past_local_node).$(tag.past_local_slot) to be entangled to $(tag.new_remote_node).$(tag.new_remote_slot) and apply correction X$(tag.correction)")
Expand All @@ -68,7 +122,7 @@ 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.

$FIELDS
$TYPEDFIELDS
"""
@kwdef struct EntanglerProt{LT} <: AbstractProtocol where {LT<:Union{Float64,Nothing}}
"""time-and-schedule-tracking instance from `ConcurrentSim`"""
Expand Down Expand Up @@ -147,7 +201,7 @@ $TYPEDEF

A protocol, running at a given node, that finds swappable entangled pairs and performs the swap.

$FIELDS
$TYPEDFIELDS
"""
@kwdef struct SwapperProt{NL,NH,CL,CH,LT} <: AbstractProtocol where {NL<:Union{Int,<:Function,Wildcard}, NH<:Union{Int,<:Function,Wildcard}, CL<:Function, CH<:Function, LT<:Union{Float64,Nothing}}
"""time-and-schedule-tracking instance from `ConcurrentSim`"""
Expand Down Expand Up @@ -237,7 +291,7 @@ $TYPEDEF

A protocol, running at a given node, listening for messages that indicate something has happened to a remote qubit entangled with one of the local qubits.

$FIELDS
$TYPEDFIELDS
"""
@kwdef struct EntanglementTracker <: AbstractProtocol
"""time-and-schedule-tracking instance from `ConcurrentSim`"""
Expand Down
Loading
Loading