diff --git a/examples/fullstack/src/Project.toml b/examples/fullstack/Project.toml similarity index 86% rename from examples/fullstack/src/Project.toml rename to examples/fullstack/Project.toml index 24b264f5..5b6c268b 100644 --- a/examples/fullstack/src/Project.toml +++ b/examples/fullstack/Project.toml @@ -7,10 +7,12 @@ version = "0.1.0" CSSMakieLayout = "5954c95d-ff03-4a38-b8f4-a6ed1c4752b2" ConcurrentSim = "6ed1e86c-fcaf-46a9-97e0-2b26a2cdb499" Crayons = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a" Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6" JSServe = "824d6782-a2ef-11e9-3a09-e5662e0c26f9" QuantumSavory = "2de2e421-972c-4cb5-a0c3-999c85908079" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" ResumableFunctions = "c5292f4c-5179-55e1-98c5-05642aab7184" Revise = "295af30f-e4ad-537b-8983-00126c2a3abe" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" @@ -18,4 +20,4 @@ SumTypes = "8e1ec7a9-0e02-4297-b0fe-6433085c89f2" WGLMakie = "276b4fcb-3e11-5398-bf8b-a0c2d153d008" [compat] -WGLMakie = "0.8.10" \ No newline at end of file +WGLMakie = "0.8.10" diff --git a/examples/fullstack/src/Sim.jl b/examples/fullstack/src/Sim.jl index a682d8fa..3f9f6d9f 100644 --- a/examples/fullstack/src/Sim.jl +++ b/examples/fullstack/src/Sim.jl @@ -69,7 +69,7 @@ function plot_alphafig(F, meta="",mfig=nothing, extrafig=nothing; hidedecor=fals if isnothing(observables) return end - obs_PURIFICATION, obs_time, obs_commtime, + running, obs_PURIFICATION, obs_time, obs_commtime, obs_registersizes, obs_node_timedelay, obs_initial_prob, obs_USE, obs_emitonpurifsuccess, logstring, showlog, obs_sampledenttimes = observables @@ -99,7 +99,6 @@ function plot_alphafig(F, meta="",mfig=nothing, extrafig=nothing; hidedecor=fals hidedecor && return F[3, 1:6] = buttongrid = GridLayout(tellwidth = false) - running = Observable(false) buttongrid[1,1] = b = Makie.Button(F, label = @lift($running ? "Stop" : "Run"), fontsize=32) leftfig = F[1:2, 1:3] rightfig = F[1:2, 4:6] @@ -148,7 +147,7 @@ function plot_alphafig(F, meta="",mfig=nothing, extrafig=nothing; hidedecor=fals USE = obs_USE[] noisy_pair = noisy_pair_func(initial_prob[]) emitonpurifsuccess = obs_emitonpurifsuccess[]==1 - + obs_sampledenttimes[] = [-1.0] protocol = FreeQubitTriggerProtocolSimulation( purifcircuit[USE]; waittime=node_timedelay[1], busytime=node_timedelay[2], @@ -184,7 +183,6 @@ function plot_alphafig(F, meta="",mfig=nothing, extrafig=nothing; hidedecor=fals coordsx = Float32[] maxcoordsy= Float32[] - mincoordsy= Float32[] for t in 0:0.1:time currenttime[] = t run(sim, t) @@ -211,12 +209,15 @@ function plot_alphafig(F, meta="",mfig=nothing, extrafig=nothing; hidedecor=fals end function plot_betafig(F, meta="",mfig=nothing; hidedecor=false, observables=nothing) - obs_PURIFICATION, obs_time, obs_commtime, + running, obs_PURIFICATION, obs_time, obs_commtime, obs_registersizes, obs_node_timedelay, obs_initial_prob, - obs_USE, obs_emitonpurifsuccess, logstring, showlog, obs_sampledenttimes, running = observables + obs_USE, obs_emitonpurifsuccess, logstring, showlog, obs_sampledenttimes = observables rightfig = F[1:2, 4:6] plotfig = rightfig[2,1:4] - waittimeax = Axis(plotfig, title="Entanglement generation wait time") + waittimeax = Axis(plotfig, title="Entanglement generation wait time", limits = (0, 5, 0, 2)) + mfig_waittimeax = nothing + (mfig!==nothing) && (mfig_waittimeax = Axis(mfig[1,1], limits = (0, 5, 0, 2))) + subfig = rightfig[1, 2:4] sg = SliderGrid(subfig[1, 1], (label="time", range=3:0.1:30, startvalue=20.3), @@ -234,16 +235,23 @@ function plot_betafig(F, meta="",mfig=nothing; hidedecor=false, observables=noth end end end + + distr = Exponential(0.4) + range = 0.05:0.1:4.95 + axes = [waittimeax] + mfig!==nothing && (push!(axes, mfig_waittimeax)) + for axis in axes + lines!(axis, range, 1/0.4 * exp.(-(collect(range) ./ 0.4))) + end on(b.clicks) do _ running[] = !running[] + if running[] == true + (empty!(axis) for axis in axes) + end end - distr = Exponential(0.4) - range = 0.05:0.1:4.95 - lines!(waittimeax, range, 1/0.4 * exp.(-(collect(range) ./ 0.4))) - on(obs_sampledenttimes) do val - empty!(waittimeax) - lines!(waittimeax, range, 1/0.4 * exp.(-(collect(range) ./ 0.4)), color=:blue) - hist!(waittimeax, val, color=:blue) + for axis in axes + lines!(axis, range, 1/0.4 * exp.(-(collect(range) ./ 0.4)), color=:blue) + hist!(axis, obs_sampledenttimes, color=:blue) end end @@ -257,19 +265,14 @@ end # the menu (the menufigures), as well as for the menufigures themselves function plot(figure_array, menufigs=[], metas=["", "", ""]; hidedecor=false, observables=nothing) - if length(menufigs)==0 - plot_alphafig(figure_array[1], metas[1]; hidedecor=hidedecor, observables=observables) - plot_betafig( figure_array[2], metas[2]; hidedecor=hidedecor, observables=observables) - plot_gammafig(figure_array[3], metas[3]; hidedecor=hidedecor, observables=observables) - else - running = plot_alphafig(figure_array[2], metas[2], menufigs[2], figure_array[1]; hidedecor=hidedecor, observables=observables) - plot_betafig(figure_array[1]; observables=push!(observables, running)) - end + plot_alphafig(figure_array[2], metas[2], menufigs[2], figure_array[1]; hidedecor=hidedecor, observables=observables) + plot_betafig(figure_array[1], metas[1], menufigs[1]; observables=observables) end ###################### LANDING PAGE OF THE APP ###################### landing = App() do session::Session + running = Observable(false) obs_PURIFICATION = Observable(true) obs_time = Observable(20.3) obs_commtime = Observable(0.1) @@ -280,8 +283,8 @@ landing = App() do session::Session obs_emitonpurifsuccess = Observable(0) logstring = Observable("") showlog = Observable(false) - obs_sampledenttimes = Observable([0.0]) - allobs = [obs_PURIFICATION, obs_time, obs_commtime, + obs_sampledenttimes = Observable([-1.0]) + allobs = [running, obs_PURIFICATION, obs_time, obs_commtime, obs_registersizes, obs_node_timedelay, obs_initial_prob, obs_USE, obs_emitonpurifsuccess, logstring, showlog, obs_sampledenttimes] keepsame=true @@ -320,13 +323,11 @@ landing = App() do session::Session editlog = Observable(false) editlogbtn = DOM.div(modifier("✎", parameter=editlog, class="nostyle"), class="backbutton", style=@lift(($editlog ? "border: 2px solid #d62828 !important;" : "border: 2px solid #003049;"))) - logs = [hstack(editlogbtn, vstack("Log...", @lift($showlog ? "[Enabled]" : "[Disabled]"), tie(logstring), class="log_wrapper")), - wrap("log2"; style="color: white;"), - wrap("log3"; style="color: white;")] + logs = [hstack(editlogbtn, vstack("Log...", @lift($showlog ? "[Enabled]" : "[Disabled]"), tie(logstring), class="log_wrapper"))] about_sections = [hstack( DOM.span(@lift($obs_USE==2 ? "Single Selection" : "Double Selection")), " | Register size: ",DOM.span(obs_registersizes) - ;style="color: $(config[:colorscheme][3]) !important; padding: 5px; background-color: white;"), wrap(""), wrap("")] + ;style="color: $(config[:colorscheme][3]) !important; padding: 5px; background-color: white;")] # Add the back and log buttons backbutton = wrap(DOM.a("←", href="/"; style="width: 40px; height: 40px;"); class="backbutton") logbutton = wrap(modifier(DOM.span("📜"), parameter=showlog, class="nostyle"); class="backbutton") @@ -334,8 +335,8 @@ landing = App() do session::Session # Info about the log: enabled/disabled loginfo = DOM.h4(@lift($showlog ? "Log Enabled" : "Log Disabled"); style="color: white;") # Add title to the right in the form of a ZStack - titles_div = [vstack(hstack(DOM.h1(titles[i]), btns), about_sections[i], loginfo, - logs[i]) for i in 1:3] + titles_div = [vstack(hstack(DOM.h1(titles[i]), btns), about_sections[1], loginfo, + logs[1]) for i in 1:3] titles_div[1] = active(titles_div[1]) (titles_div[i] = wrap(titles_div[i]) for i in 2:3) titles_div = zstack(titles_div; activeidx=activeidx, anim=[:static] @@ -437,54 +438,80 @@ landing = App() do session::Session end + nav = App() do - img1 = DOM.img(src="https://github.com/adrianariton/QuantumFristGenRepeater/blob/master/entanglement_flow.png?raw=true"; style="height:30vw; width: fit-contentt;border-bottom: 2px solid black; margin: 5px;") - img2 = DOM.img(src="https://github.com/adrianariton/QuantumFristGenRepeater/blob/master/purification_flow.png?raw=true"; style="height:30vw; width: fit-contentt;border-bottom: 2px solid black margin: 5px; transform: translateX(-25px);") + img1 = DOM.img(src="https://github.com/adrianariton/QuantumFristGenRepeater/blob/master/assets/entanglement_flow.png?raw=true"; style="height:30vw; width: fit-contentt;border-bottom: 2px solid black; margin: 5px;") + img2 = DOM.img(src="https://github.com/adrianariton/QuantumFristGenRepeater/blob/master/assets/purification_flow.png?raw=true"; style="height:30vw; width: fit-contentt;border-bottom: 2px solid black margin: 5px; transform: translateX(-25px);") + img3 = DOM.img(src="https://github.com/adrianariton/QuantumFristGenRepeater/blob/master/assets/purifperformance.png?raw=true"; style="height:30vw; width: fit-contentt;border-bottom: 2px solid black; margin: 5px;") list1 = DOM.ul( - DOM.li(md"""`circuit`: The purification circuit being used (can be 2 for **Single Selection** and 3 for **Double Selection**)"""), - DOM.li(md"""`pauli error prob`: The Pauli noise for initial entanglement generation"""), - DOM.li(md"""`channel delay`(s): The time it takes for a message to get from the sender to the receiver."""), - DOM.li(md"""`recycle purif pairs` (also called `emitonpurifsuccess` in the code): If the protocol should use purified pairs reccurently to create even stronger ones (fidelity-wise)."""), + DOM.li("""initial fidelity: The Pauli noise for initial entanglement generation"""), + DOM.li("""channel delay(s): The time it takes for a message to get from the sender to the receiver."""), + DOM.li("""recycle purif pairs (also called `emitonpurifsuccess` in the code): If the protocol should use purified pairs reccurently to create even stronger ones (fidelity-wise)."""), + DOM.li("""circuit: The purification circuit being used (can be 2 for **Single Selection** and 3 for **Double Selection**)"""), ) list2 = DOM.ul( - DOM.li(md"""The network graph *(left side)*"""), - DOM.li(md"""The sliders and the number of pairs of each fidelity *(top right and top)*"""), - DOM.li(md"""The maximum fidelity among all existing pairs *(right)*"""), + DOM.li("""The network graph (left side)"""), + DOM.li("""The sliders (top right and top)"""), + DOM.li("""Information about the current part of the protocol (right)"""), ) - text = md""" - # Entanglement generation in a network using Delayed Channels for communication + text = [md""" + # Entanglement generation in a network using delayed channels for communication Using this $(DOM.a("simulation", href="/1")), one can vizualize the processes happening in a network of nodes, as they communicate with eachother, requesting entanglement or purification of already entangled pairs. - The simulation consists of 3 parts, from which only the first one is available. - - ## Part 1: Entanglement and Purification between Alice and Bob + The simulation consists of 2 parts: entanglement generation and entanglement purification. The main goal of this simulation is to help in the understanding and visualization of the Free Qubit Trigger Protocol, with different parameters. ### About the Free Qubit Trigger Protocol - The protocol consists (for now) of two steps: entanglement and purification. It has the following parameters: + The protocol consists of two steps: entanglement and purification. It has the following parameters: $(list1) - The protocol can be split in two parts: **Entanglement Generation**, and **Purification** (wheather reccurent or not). + The protocol can be split in two parts: **Entanglement Generation**, and **Purification**, both of which have their own figures in the simulation. + In the 2 figures, one can modify the parameters specific to the targeted step of the protocol. The way they work can be visualized in the diagrams on the right. ### This $(DOM.a("simulation", href="/1")) consists of a layout containing the following components: $(list2) + View the simulation $(DOM.a("here", href="/1"))! - View the simulation here! - $(vstack(DOM.a("SIMULATION", href="/1"))) - """ + + # Understanding the plots and the simulation + + ## Entanglement Generation + + The chronology of operations for the entanglegen process can be viewed in the first diagram. + There is one single plot (on the left of the figure) other than the node graph. The plot plots the random + amount of time it takes for an entangled pair to generate (when receiving **INITIALIZE_STATE**). The time is consistent with an exponential distribution. + + ## Purification + + The chronology of operations for the purification process can be viewed in the second diagram. + We have 2 plots other than the node graph: a big one (bottom), and a smaller one (top, near the sliders). + Both plots show information about fidelity. The big one plots the maxmimum fidelity among all pairs vs time, + and the smaller one plots a histogram of all the pairs' fidelities. + + One can choose between two purification circuits: Double Selection (3to1) and Single Selection (2to1) + Their performance is different, Double Selection resulting in a higher fidelity than Single Selection. + + One can view their performance in the following plot, which plots **final vs initial fidelity (blue)** and **success rate vs initial fidelity (yellow)**: + $(img3) + + (first column - variants of single selection, colums 2 to 4 - variants of double selection) + + + """] return hstack( wrap(text; style="width:50vw;"), vstack(DOM.h2("Entanglement process flow"), img1, DOM.h2("Purifier process flow"), img2; style="width:50vw;", class="align-center justify-center"), CSSMakieLayout.formatstyle ) end + ## # Serve the Makie app isdefined(Main, :server) && close(server); diff --git a/examples/fullstack/src/setup.jl b/examples/fullstack/src/setup.jl index 247ab4dc..15cf256f 100644 --- a/examples/fullstack/src/setup.jl +++ b/examples/fullstack/src/setup.jl @@ -142,7 +142,7 @@ end end @resumable function entangle(sim::Simulation, protocol::FreeQubitTriggerProtocolSimulation, network, node, remotenode, noisy_pair = noisy_pair_func(0.7) - , logfile=nothing, sampledentangledtimes=[nothing], entangletimedist=Exponential(0.4)) + , logfile=nothing, sampledentangledtimes=[false], entangletimedist=Exponential(0.4)) waittime = protocol.waittime busytime = protocol.busytime channel = network[node=>remotenode, protocol.keywords[:simple_channel]]