Skip to content
Open
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d8b724e
added new interactive example (no visualization yet) termed 'piecemaker'
Luisenden Sep 17, 2024
337fc92
added depolarization channel for stabilizer state repr and updated fi…
Luisenden Oct 1, 2024
39ae298
execute ghz generation only once, only entanglement generation should…
Luisenden Oct 4, 2024
54d9ad2
simple run finished, runs fusion protocol multiple times and collects…
Luisenden Oct 8, 2024
307fd09
updated README
Luisenden Oct 8, 2024
f7a3f47
adjustements in simulation setup and run script, noise applied after …
Luisenden Oct 31, 2024
8a14160
deleted init function, moved param value setting to run script
Luisenden Nov 6, 2024
0957cf6
changed GHZConsumer to FusionConsumer
Luisenden Nov 6, 2024
0aaeae1
deleted tag Piecemaker
Luisenden Nov 6, 2024
be08d75
reset project env in parent directory and added specific dependencies…
Luisenden Nov 6, 2024
81f12d1
deleted .DS_Store; updated local env
Luisenden Nov 6, 2024
cef2e06
updated readme
Luisenden Nov 6, 2024
467a314
Uptdated to event-driven implementation; added slot variables to Enta…
Luisenden Nov 21, 2024
77631f2
cleaned up code; deleted FusionSwitchDiscreteProtocol as it is not ne…
Luisenden Dec 3, 2024
e7d4349
deleted functions not in use (entangler functions and fusion function)
Luisenden Dec 3, 2024
5ab85ce
deleted .vscode
Luisenden Dec 3, 2024
46681bb
added explanation to tag FusionCounterpart
Luisenden Dec 3, 2024
badefaa
changed order of parameters in fusioncircuit to (control, target); ad…
Luisenden Dec 3, 2024
3a40643
extended function apply_noninstant! to work with depolarizing noise (…
Luisenden Dec 3, 2024
9a12dd6
updated readme
Luisenden Dec 4, 2024
751c5b1
updated readme
Luisenden Dec 4, 2024
e9761d6
Merge branch 'master' into piecemaker
Luisenden Jul 15, 2025
83276fe
reverted to whats on master
Luisenden Jul 15, 2025
c032be4
fixed open loop
Luisenden Jul 15, 2025
b81b390
updated ProtocolZoo to align with original source
Luisenden Jul 15, 2025
87a5816
updated switches.jl to align with original source
Luisenden Jul 15, 2025
47e6134
updated CircuitZoo to align with original source
Luisenden Jul 15, 2025
1847ccc
fix small typo
Luisenden Jul 15, 2025
c703404
Merge branch 'master' into piecemaker
Luisenden Aug 8, 2025
38d0784
simple piecemaker updated
Luisenden Aug 8, 2025
315a4ab
added small vizualisation
Luisenden Aug 12, 2025
720fd3e
typo in file name
Luisenden Aug 12, 2025
1b4b477
deleted depr tests
Luisenden Oct 6, 2025
ff44bee
Merge branch 'master' into piecemaker
Luisenden Oct 6, 2025
97caf9e
updated simple runs and added interactive html with wgl makie
Luisenden Oct 9, 2025
ca48d0d
updated readme, renamed web-app version
Luisenden Oct 20, 2025
6ae9e1a
consolidated web-app with setup; small updates to static plot and sim…
Luisenden Oct 20, 2025
31b6b2a
added examples to test_examples
Luisenden Oct 21, 2025
5c23612
added docstrings to setup file
Luisenden Oct 21, 2025
669528c
small final updates
Luisenden Oct 21, 2025
502d33f
consolidated print statements
Luisenden Nov 2, 2025
e82c3a5
Merge branch 'master' into piecemaker
Luisenden Nov 2, 2025
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
17 changes: 17 additions & 0 deletions examples/piecemakerswitch/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[deps]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tests run with a different project.toml file -- in case some tests fail with a missing dependency, probably you just need to add the dependency to the test project.toml

Copy link
Contributor Author

@Luisenden Luisenden Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when I run julia --project=. runtests.jl in test I get the following error

"ERROR: LoadError: UndefVarError: onchange not defined in Main.var"##234""

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that might be because of a weird setup for your project environment; we can debug it with ] status

Bonito = "824d6782-a2ef-11e9-3a09-e5662e0c26f8"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
ConcurrentSim = "6ed1e86c-fcaf-46a9-97e0-2b26a2cdb499"
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
NetworkLayout = "46757867-2c16-5918-afeb-47bfcb05e46a"
QuantumClifford = "0525e862-1e90-11e9-3e4d-1b39d7109de1"
QuantumSavory = "2de2e421-972c-4cb5-a0c3-999c85908079"
ResumableFunctions = "c5292f4c-5179-55e1-98c5-05642aab7184"
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
WGLMakie = "276b4fcb-3e11-5398-bf8b-a0c2d153d008"
59 changes: 59 additions & 0 deletions examples/piecemakerswitch/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Distributing a GHZ state with a quantum entanglement switch

Live version is available at [areweentangledyet.com/piecemakerswitch/](https://areweentangledyet.com/piecemakerswitch/).

In this setup, multiple nodes (user nodes) connect to a central node (switch node) trough bipartite entangled states. The switch node performs fusion operations on these shared states to create a GHZ state among the user nodes. The goal is to do the latter as memory efficient as possible. Each of the $n$ clients can store one memory qubit in its memory buffer and one qubit at the switch side. In addition the switch's register holds a dedicated 'piecemaker' slot - a qubit in the $|+\rangle$ state, which all successfull clients fuse their switch'side qubits with. We term this protocol the _piecemaker_ protocol, see [Prielinger et al., 2025](https://arxiv.org/abs/2508.14737).

In each time step, $n$ entanglement generation processes run in parallel. Upon creation of an entanglement link, it is fused with the piecemaker qubit. Once all clients went through this fusion operation, the piecemaker qubit is measured. This projects the state back to the clients, resulting in the desired shared GHZ state.
The fusion operation is performed on the switch node: Let's take a client who just managed to generate a bipartide entangled state -- entangled link -- with its associated qubit at the switch side. The switch executes a `CNOT` gate on the client's qubit (target) and the piecemaker qubit (control). Next, the switch measures the client qubit in the computational basis and sends the outcome to the client (in order to apply the necessary Pauli correction). This procedure merges the bipartide state into the (entangled) state that the piecemaker qubit is currently part of, modulo any required Pauli corrections.

NOTE: The memories residing in the nodes' `Register`s suffer from depolarizing noise, see [`Depolarization`](https://qs.quantumsavory.org/stable/API/#QuantumSavory.Depolarization).

The `setup.jl` file implements all necessary base functionality.
The other files run the simulation and generate visuals in a number of different circumstances:
1. `simple_run.jl` A single simulator script convenient for exploratory coding, running a numer of Monte Carlo simulations;
2. `live_visualization_interactive` A web-app version of the simulator;
3. `static_viz.jl` A script running a number of of simulations like the ones in point 1, followed by plotting the fidelity over the protocol's execution time.

Documentation:
- [The "How To" doc page on setting up this simulation](https://qs.quantumsavory.org/dev/howto/piecemakerswitch/piecemakerswitch)

### Protocol flow

```mermaid
sequenceDiagram
participant Client1
participant ClientN
participant SwitchNode
participant Log
Note over Client1,SwitchNode: Round 1 (1 unit time)
par Entanglement Generation
Client1->>+SwitchNode: Try to generate entanglement
ClientN->>+SwitchNode: Try to generate entanglement
end
SwitchNode->>SwitchNode: Run fusions with successful clients
par Send Measurement Outcomes
SwitchNode-->>-Client1: Send measurement outcomes
SwitchNode-->>-ClientN: Send measurement outcomes
end
par Apply Corrections (No time cost)
Client1->>Client1: Apply correction gates
ClientN->>ClientN: Apply correction gates
end
loop Check Fusion Status (No time cost)
SwitchNode->>SwitchNode: Check if all clients are fused
alt All clients fused
SwitchNode->>SwitchNode: Measure piecemaker
SwitchNode->>SwitchNode: Compute fidelity to GHZ state
SwitchNode->>Log: Log fidelity and time [END OF PROTOCOL]
else
SwitchNode->>SwitchNode: Keep checking
end
end
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check the readme of https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/simpleswitch and https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/state_explorer to add similar structural components like a spelled out link to docs and a link to live example (just make up one in the same style, e.g. areweentagledyet...../PICK_A_NAME) -- I will make sure it runs by the time we merge this

162 changes: 162 additions & 0 deletions examples/piecemakerswitch/live_visualization_interactive.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
# Live visualization of the piecemaker switch protocol
include("setup.jl")

using Base.Threads
using WGLMakie
WGLMakie.activate!()

using Bonito
using Markdown
const custom_css = Bonito.DOM.style("ul {list-style: circle !important;}")

logging = Observable(Point2f[]) # for plotting

function push_to_logging!(logging::Observable, t::Float64, fidelity::Float64)
push!(logging[], Point2f(t, fidelity))
end

function prepare_sim(fig::Figure, n::Int, link_success_prob::Float64, mem_depolar_prob::Float64)

repr = QuantumOpticsRepr()

decoherence_rate = -log(1 - mem_depolar_prob)
noise_model = Depolarization(1 / decoherence_rate)

switch = Register([Qubit() for _ in 1:(n+1)], [repr for _ in 1:(n+1)], [noise_model for _ in 1:(n+1)])
clients = [Register([Qubit()], [repr], [noise_model]) for _ in 1:n]

graph = star_graph(n + 1)
net = RegisterNet(graph, [switch, clients...])
sim = get_time_tracker(net)

# Attach the network plot to net and capture its obs
_, ax_net, _, net_obs = registernetplot_axis(fig[1, 2], net)
ax_net.title = "Network of n=5 users (live Δt = 0.1s)"
# Fix the visible ranges
xlims!(ax_net, -15, 15)
ylims!(ax_net, -15, 15)
ax_net.aspect = Makie.DataAspect() # keep aspect ratio
Makie.deregister_interaction!(ax_net, :scrollzoom) # disable zoom and pan interactions
Makie.deregister_interaction!(ax_net, :dragpan)

@process PiecemakerProt(sim, n, net, link_success_prob, -1) # set rounds=1

return sim, net, net_obs
end

# A helper to add parameter sliders to visualizations
function add_conf_sliders(fig)
conf = Dict(
:link_success_prob => 0.5,
:mem_depolar_prob => 0.1,
)
conf_obs = Observable(conf)
sg = SliderGrid(
fig,
(label = "link success prob",
range = 0.05:0.05:1.0, format = "{:.2f}", startvalue = conf[:link_success_prob]),
(label = "mem depolar prob",
range = 0.05:0.05:1.0, format = "{:.2f}", startvalue = conf[:mem_depolar_prob]),
width = 300,
)

names = [:link_success_prob, :mem_depolar_prob]
for (name,slider) in zip(names,sg.sliders)
on(slider.value) do val
conf_obs[][name] = val
end
end
conf_obs
end

# Serve the Makie app
landing = Bonito.App() do

n = 5 # number of clients

fig = Figure(resolution = (800, 600))
ax_fid = Axis(fig[1, 1], xlabel="Δt (time steps)", ylabel="Fidelity to GHZₙ", title="Fidelity")
scatter!(ax_fid, logging, markersize = 8)
ylims!(ax_fid, 0, 1.05)
xlims!(ax_fid, 0, 30)

running = Observable{Union{Bool,Nothing}}(false)
fig[2, 1] = buttongrid = GridLayout(tellwidth = false)
buttongrid[1,1] = b = Makie.Button(
fig,
label = @lift($running ? "Running..." : "Run once"),
height = 30, tellwidth = false,
)

conf_obs = add_conf_sliders(fig[2, 2])

on(b.clicks) do _
if running[] # ignore while already running
return
end
running[] = true
@async begin
try # run the sim
sim, net, net_obs = prepare_sim(fig, n, conf_obs[][:link_success_prob], conf_obs[][:mem_depolar_prob])
t = 0
while true
t += 1
if length(logging[]) > 10
break
end
run(sim, t)
notify(net_obs)
notify(logging)
sleep(0.1)
end
finally
running[] = false
logging[] = Point2f[] # clear points for next run
end
end
end

content = md"""
Pick simulation settings and hit “Run once”. The left panel plots the running fidelity to the target GHZ state; the right panel shows the network state as it evolves over 10 simulation rounds.

$(fig.scene)

# GHZ state distribution with a quantum entanglement switch

This demo simulates 10 rounds of GHZ-state distribution in a star-shaped network with a central switch node and n client nodes. Each client holds one memory qubit locally and one at the switch. The switch has an extra “piecemaker” qubit (slot n+1) that is initialized in the |+⟩ state; it is used to fuse all successful links into an n-party GHZ state.

What happens during one run:
- Per time step, the switch attempts to entangle with each client in parallel (success probability set by the slider “link success prob”).
- When a client<>switch entanglement attempt succeeds, the switch immediately fuses the client’s switch-side qubit with the piecemaker via a CNOT, measures the client qubit in Z, and sends the outcome to the client. The client applies necessary corrections.
- After all clients have been fused, the piecemaker is measured in X. The first client receives that outcome and applies a Z correction if needed.
- The current n-qubit state (the clients’ memory qubits) is compared to the ideal GHZₙ target state. The resulting fidelity is plotted as a point on the left over the number of taken time steps Δt.

Noise model:
- Memory qubits are subject to depolarizing noise ([`Depolarization`](https://qs.quantumsavory.org/stable/API/#QuantumSavory.Depolarization) background). The slider “mem depolar prob” controls the memory depolarization probability.

UI guide:
- Left: fidelity vs simulation time Δt. Points accumulate across runs so you can compare settings.
- Right: network snapshot. Edges appear when links are established; updates every 0.1s of real time.
- Sliders: tune link success probability and memory depolarization probability before each run.
- Button: starts a single run with the current settings.

NOTE that this is a simplified simulation for demonstration purposes. In particular, it assumes instantaneous gates as well as classical communication. The only time inducing steps are the attempts for heralded entanglement generation (Δt = 1 time step each).

[Browse or modify the code for this simulation on GitHub.](https://github.com/QuantumSavory/QuantumSavory.jl/tree/master/examples/piecemakerswitch/live_visualization_interactive.jl)
"""
return Bonito.DOM.div(Bonito.MarkdownCSS, Bonito.Styling, custom_css, content)
end;


isdefined(Main, :server) && close(server);
port = parse(Int, get(ENV, "QS_GHZSWITCH_PORT", "3000"))
interface = get(ENV, "QS_GHZSWITCH_IP", "0.0.0.0") # Bind to all interfaces
proxy_url = get(ENV, "QS_GHZSWITCH_PROXY", "")
server = Bonito.Server(interface, port; proxy_url);
Bonito.HTTPServer.start(server)
Bonito.route!(server, "/" => landing);


@info "app server is running on http://$(interface):$(port) | proxy_url=`$(proxy_url)`"

wait(server)
Loading
Loading