Getting started
Recall the generic template to get started.
# Choose backend and round counts
state_type::DensityMatrix = DensityMatrix() #or StateVector
total_rounds::Int = # Number of rounds, 1...N
computation_rounds::Int = # Number of rounds,1,...,N
# Grover graph
num_vertices::Int = # Also becomes number of qubits
graph = Graph(num_vertices)::Graph # Uses Graphs.jl
# Specify graph using Graphs.jl API
input = (indices = (),values = ())::NamedTuple # Input classical data
output = ()::Tuple # Output qubits classical outcomes BQP
# Julia is indexed 1, hence a vertex with 0 index is a flag for no flow
function forward_flow(vertex::Int)
v_str = string(vertex)
forward = Dict(
"current" =>future,
"1" => 0) # indicates vertex 1 does not have a flow, specify all qubits.
forward[v_str]
end
secret_angles::Vector{Float64} = # Angles secret from Bob
# Keep as is
para::NamedTuple= (
graph=graph,
forward_flow = forward_flow,
input = input,
output = output,
secret_angles=secret_angles,
state_type = state_type,
total_rounds = total_rounds,
computation_rounds = computation_rounds)
Using para
The NamedTuple
with variable name para
is the entry point for all operations developed in this package.
Basic computation
To simply run the algorithm, unblinded, then call run_mbqc
run_mbqc(para)
and for a blind computation of the same input, then call run_ubqc
run_ubqc(para)
Since both are computing the same graph, except that run_ubqc
hides the state and both are universal, then the outcome should be the same.
Verification
Trustworthy
To run the verification of a noiseless and trustworthy server.
vbqc_outcome = run_verification_simulator(TrustworthyServer(),Verbose(),para)
Note that additionally to para
, there are two type calls, TrustWorthyServer
and Verbose
. Due to Julia's use of multiple dispatch, algorithms make use of this paradigm. In this case Trustworthy
indicates there is no noise and no maliciousness. And the flag Verbose
retuns more lengthy result data, as opposed to the Terse
type.
vbqc_outcome = run_verification_simulator(TrustworthyServer(),Terse(),para)
Malicious
Here malicious is implemented as an additionaly angle the server adds to each qubit's measurement angle.
For the Verbose
outcome
malicious_angles = π/2
malicious_vbqc_outcome = run_verification_simulator(MaliciousServer(),Verbose(),para,malicious_angles)
For the Terse
outcome
Noisyness
From QuEST, there are pre-built decoherence emulators.
Single qubit
Damping, dephasing, depolarising and pauli noise models have been implemented and tested. Note there are also Kraus maps, but testing is in development.
To run a noisy verification, call the same run_verification_simulaor
, but this time the server is a NoisyServer
which has a noise model. A noise model is called, which is then passed to the server. The server tells the verification simulator what noise is needed.
To ensure probabilities are small, a scaling value is applied.
# Prob scaling
p_scale = 0.05
The following examples show how easy it is to insert a pre-made noise model.
Damping
# Damping
p = [p_scale*rand() for i in vertices(para[:graph])]
model = Damping(Quest(),SingleQubit(),p)
server = NoisyServer(model)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Dephasing
# Dephasing
p = [p_scale*rand() for i in vertices(para[:graph])]
model = Dephasing(Quest(),SingleQubit(),p)
server = NoisyServer(model)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Depolarising
# Depolarising
p = [p_scale*rand() for i in vertices(para[:graph])]
model = Depolarising(Quest(),SingleQubit(),p)
server = NoisyServer(model)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Pauli
# Pauli
p_xyz(p_scale) = p_scale .* [rand(),rand(),rand()]
p = [p_xyz(p_scale) for i in vertices(para[:graph])]
model = Pauli(Quest(),SingleQubit(),p)
server = NoisyServer(model)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Vector of models
# Vector of noise models
model_vec = [Damping,Dephasing,Depolarising,Pauli]
p_damp = [p_scale*rand() for i in vertices(para[:graph])]
p_deph = [p_scale*rand() for i in vertices(para[:graph])]
p_depo = [p_scale*rand() for i in vertices(para[:graph])]
p_pauli = [p_xyz(p_scale) for i in vertices(para[:graph])]
prob_vec = [p_damp,p_deph,p_depo,p_pauli]
models = Vector{NoiseModels}()
for m in eachindex(model_vec)
push!(models,model_vec[m](Quest(),SingleQubit(),prob_vec[m]))
end
server = NoisyServer(models)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Kraus map
This functionality needs to be tested, and a warning will display the untested quality.
This snippet is an example of how the user will call a single qubit Kraus model.
# Krau
p = # some Kraus operators
model = Kraus(Quest(),SingleQubit(),p)
server = NoisyServer(model)
vbqc_outcome = run_verification_simulator(server,Verbose(),para)
Double qubit
Many of the above noise models are also available as pairwise operations. These are not yet ready for production.
$N$ Qubit and Density operators
The Kraus maps can be generalised for $N$ qubit operations. These are not yet ready for production.
There is also density matrix mixing noise. These are not yet ready for production.
Data analysis
Once verification is complete, it is helpful to have some sense of the results.
TO DO: Add examples of statistical/numericalresults
Hardware specific
Definitely a future to do.