Tutorial

A step-by-step introduction to the main facilities of QuEST-MMA.

Table of contents:
        • Connecting to QuEST
        • Creating quantum registers
        • Specifying gates
        • Applying circuits
        • Analysing quantum states

Connecting to QuEST

Import the QuEST-MMA package . Further functions will be loaded once connected to an QuEST environment.

Import["https://qtechtheory.org/questlink.m"]

One then connects to a QuEST runtime environment, which can be local or remote.

?CreateRemoteQuESTEnv
?CreateLocalQuESTEnv
?CreateDownloadedQuESTEnv

We’ll automatically download a QuEST executable and locally connect.

env = CreateDownloadedQuESTEnv[];

This loads further package functions and circuit symbols, listed below.

?QuEST`*

Creating quantum registers

Now that we’re connected to a QuEST runtime environment, we can allocate quantum registers as state vectors or density matrices.

numQb = 9;
ψ = CreateQureg[numQb];
ρ = CreateDensityQureg[numQb];

These registers are stored in the environment which may be remote. The Mathematica kernel only knows the IDs by which to identify these structures to the QuEST environment.

ψ

ρ

GetAllQuregs[]

This means we can create, operate on and study states that are too large to fit in Mathematica, or even this machine!

InitPlusState @ ψ;
CalcProbOfOutcome[ψ, 5, 1]

?InitPlusState
?CalcProbOfOutcome

With some overhead, we can view the state with GetQuregMatrix (which is initially ψ = |0⟩ and ρ = |0⟩⟨0|).

Dimensions @ GetQuregMatrix[ψ]

Dimensions @ GetQuregMatrix[ρ]

The state vectors will live in the QuEST environment until individually destroyed...

DestroyQureg[ψ]
DestroyQureg[ρ]

or all at once.

DestroyAllQuregs[];

Specifying gates

Individual gates have syntax (Subscript[GateName, targetQubit])  where the targetQubit index is subscript (ctrl-minus) and indexes from 0. E.g. (Subscript[H, 3]) represents a Hadamard on the 4th qubit

?H

Some gates additionally accept parameters in square brackets, e.g. (Subscript[Ry, 2])[ϕ]

?Ry

This can include matrices, e.g. (Subscript[U, 3])[(({{0, i}, {Exp[.3i], 0}}))] ...

?U

and lists of matrices, e.g.  (Subscript[Kraus, 2])[{ (({{1, 0}, {0, (Sqrt[1-p])}})),  (({{0, (Sqrt[p])}, {0, 0}}))}] ...

?Kraus

Multiple target qubits are comma separated, or supplied as a list, e.g. (Subscript[SWAP, 0,3]) and (Subscript[M, 0,1,2,3]) ...

?SWAP
?M

unless specified as Pauli sequences, e.g. R[ϕ, (Subscript[X, 2])(Subscript[Y, 3])(Subscript[Z, 0])]

?R

Controlled gates are merely wrapped in (Subscript[C, control qubits])[ ],   e.g. (Subscript[C, 1,2])[ (Subscript[X, 3])] is a doubly-controlled NOT

(Subscript[C, 0,1,2])[(Subscript[U, 6,3])[(({{(E^(I (π/3))), 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}}))]];

Some operations like decoherence are only relevant for density matrices (states created with createDensityQureg)

?Deph
?Depol
?Damp
?Kraus

Applying circuits

A circuit can be written verbosely as a list (to be applied left-to-right) of gates...

{(Subscript[H, 2]), (Subscript[Rz, 1])[.3], (Subscript[C, 4])[(Subscript[X, 3])],  (Subscript[C, 0,1,2])[(Subscript[SWAP, 4,5])]};
DrawCircuit[%]

or concisely as a direct product wrapped in Circuit[] to prevent automatic commutation (or to be reversed, Operator[] )

Circuit[ (Subscript[H, 2]) (Subscript[Rz, 1])[.3] (Subscript[C, 4])[(Subscript[X, 3])] (Subscript[C, 0,1,2])[(Subscript[SWAP, 4,5])] ]

Operator[ (Subscript[H, 2]) (Subscript[Rz, 1])[.3] (Subscript[C, 4])[(Subscript[X, 3])] (Subscript[C, 0,1,2])[(Subscript[SWAP, 4,5])] ]

Circuits can be specified in terms of symbols/parameters, though which must be assigned numerical values before simulation.

m1 = (({{0, I}, {Exp[.3I], 0}}));
m2 = (({{1, 0, 0, 0}, {0, 0, 1, 0}, {0, 1, 0, 0}, {0, 0, 0, 1}}));

u[θ_]:= Circuit[
 (Subscript[S, 5])(Subscript[T, 7]) (Subscript[Y, 8])(Subscript[Ry, 3])[θ] (Subscript[C, 3])[(Subscript[Rz, 2])[θ]](Subscript[C, 8,7,6])[(Subscript[Z, 5])](Subscript[M, 0 ])(Subscript[Ry, 3])[θ] (Subscript[M, 1,3,4]) (Subscript[SWAP, 0,3]) (Subscript[C, 5])[(Subscript[SWAP, 4,6])](Subscript[Depol, 2,4])[θ/100] (Subscript[Deph, 7,6])[θ/400](Subscript[M, 0])(Subscript[H, 2])(Subscript[X, 3])(Subscript[T, 5])(Subscript[C, 0,2,3,4])[(Subscript[X, 1])] (Subscript[C, 0])[(Subscript[U, 1,7])[m2]](Subscript[U, 2,4])[m2] (Subscript[U, 7])[m1]  (Subscript[SWAP, 0,1])(Subscript[Depol, 5])[θ/300] (Subscript[Deph, 0])[θ/200]   (Subscript[Damp, 7])[θ/500] (Subscript[C, 2,3])[(Subscript[SWAP, 4,5])] (Subscript[U, 3,1])[m2] (Subscript[U, 4,5])[m2] (Subscript[U, 6,8])[m2] (Subscript[X, 0])  (Subscript[U, 0,1])[m2] (Subscript[C, 2,3,4,5])[(Subscript[T, 6])] (Subscript[C, 0,2,4,5])[(Subscript[U, 1,3])[m2]](Subscript[C, 6,8])[(Subscript[U, 7])[m1]] 
];

DrawCircuit @ u[θ]

Circuits can be applied to instantiated quantum registers through ApplyCircuit

ψ = CreateQureg[3];
ApplyCircuit[ Circuit[(Subscript[H, 0])(Subscript[X, 1])(Subscript[Ry, 2])[π/3]], ψ];
GetQuregMatrix[ψ]

?ApplyCircuit

ApplyCircuit returns a list of the random measurement outcomes (if any), ordered and grouped by the ordering of M in the circuit

ApplyCircuit[ Circuit[ (Subscript[M, 0]) (Subscript[M, 1,2])], ψ]

Remember these measurements are destructive

ApplyCircuit[ Circuit[ (Subscript[M, 0,1,2])], ψ]

Remember that symbols/parameters in the circuit must be given numerical values before evaluation

ApplyCircuit[ (Subscript[Rx, 0])[ϕ], ψ]

Circuits applied to density matrices are no different

ApplyCircuit[u[0], InitPlusState @ CreateDensityQureg[9]]

Analysing quantum states

DestroyAllQuregs[];

Quantum registers can be studied without expensively copying their state vector or density matrix to Mathematica from the QuEST environment.

ρ = InitPlusState @ CreateDensityQureg @ numQb;
ApplyCircuit[ (Subscript[Depol, 0,1])[.1], ρ];
CalcPurity[ρ]
?CalcPurity

ψ = InitPlusState @ CreateQureg @ numQb;
CalcFidelity[ρ, ψ]
?CalcFidelity

CalcProbOfOutcome[ρ, 0, 0]
ApplyCircuit[ (Subscript[Damp, 0])[.1], ρ];
CalcProbOfOutcome[ρ, 0, 0]
?CalcProbOfOutcome

This allows us to express complicated calculations succinctly, and evaluate them quickly.

ApplyCircuit[u[0],InitPlusState @ ψ];

params = Range[0,π,.01];
fids = Table[
	ApplyCircuit[u[θ],InitPlusState @ ρ];
	CalcFidelity[ρ, ψ],
	{θ, params}
];

Here we’ve calculated how smoothly varying the noise level θ in our complicated u[θ] circuit (drawn here) affects the fidelity with its initial |+⟩⟨+| state. Note the results here are random since our circuit contains projective measurement gates.

ListPlot[
	Transpose[{params,fids}], 
	AxesLabel-> {"θ","(Bra[ψ])ρ(Ket[ψ])"},
	Filling->Bottom
]

Finally, we free the state-vectors from the QuEST environment and disconnect from quest_link (killing the process).

DestroyAllQuregs[]; 
DestroyQuESTEnv[env];