- Madhav Krishnan Vijayan (mkv.215@gmail.com)
- Simon Devitt
- Peter Rohde (dr.rohde@gmail.com, www.peterrohde.org)
- Alexandru Paler
- Casey Myers
- Jason Gavriel
- Michał Stęchły(michal.stechly@zapatacomputing.com)
- Scott Jones (scott@gandalfsoftware.com)
- Athena Caesura
Jabalizer is a quantum graph state compiler for quantum circuits written in Julia. It has the functionality to manipulate stabilizer states and graph states and provides generic functions able to operate within both pictures and dynamically convert between them, allowing arbitrary Clifford circuits to be simulated and converted into graph state language, and vice-versa.
Jabalizer also provides functionality to convert Clifford + T gate circuits to an aglorithm specific graph state using the icm
module. The computation can now be implemented by passing this graph state and a measurement procedure to a quantum backend.
You can learn more about the Julia language at www.julialang.org.
A techical paper on Jabalizer can be found here https://arxiv.org/abs/2209.07345
Jabalizer can be installed like any Julia package.
type ]
in the Julia REPL to enter the pkg mode and enter
pkg> add Jabalizer
The module can be tested using
pkg> test Jabalizer
While simulating arbitrary quantum circuits is classically inefficient with exponential resource overhead, via the Gottesman-Knill theorem it is known that circuits comprising only Clifford operations (ones that commute with the Pauli group) can be efficiently simulated using the stabilizer formalism. In the stabilizer formalism an n-qubit state is defined as the simultaneous positive eigenstate of n 'stabilizers', each of which is an n-fold tensor product of Pauli operators (I,X,Y,Z) and a sign (+/-). That is, for each stabilizer
satisfies
As an example, the Bell state
can equivalently be represented by the two stabilizers
The orthogonal Bell state
differs only slightly with stabilizers,
Similarly, the three-qubit GHZ state
can be represented by the three stabilizers,
Evolving stabilizer states can be performed in the Heisenberg picture by conjugating the stabilizers with the unitary operations acting upon the state since for the evolution,
we can equivalently write,
where,
stabilizes the evolved state
Thus the rule for evolving states in the stabilizer formalism is to simply update each of the n stabilizers via
The efficiency of classically simulating stabilizer circuits was subsequently improved upon by Aaronson & Gottesman using the so-called CHP approach which tracks both stabilizers and anti-stabilizers, improving the performance of measurements within this model. Jabalizer employs the highly-optimised STIM simulator as its CHP backend.
A graph state is defined as a set of n qubits represented as vertices in a graph, where qubits are initialised into the
state and edges between them represent the application of controlled-phase (CZ) gates. This leads to the general stabilizer representation for graph states,
for each qubit i, where $$ n_i $$ denotes the graph neighbourhood of vertex i.
For example, the set of stabilizers associated with the graph,
is given by,
Viewing this as a matrix note that the X operators appear along the main diagonal, which the locations of the Z operators define the adjacency matrix for the graph.
All stabilizer states can be converted to graph states via local operations, achieved via a tailored Gaussian elimination procedure on the stabilizer tableau. Jabalizer allows an arbitrary stabilizer state to be converted to a locally equivalent graph state and provide the associated adjacency matrix for the respective graph.
Here's some simple Jabalizer code that executes the gate sequence used to generate a GHZ state, display the associated set of stabilizers, and then convert it to its locally equivalent graph state, which is then manipulated via several Pauli measurements and finally converted back to stabilizer form.
using Jabalizer
# Prepare a 6-qubit GHZ state
n = 6
state = zero_state(n)
Jabalizer.H(1)(state)
Jabalizer.CNOT(1,2)(state)
Jabalizer.CNOT(1,3)(state)
Jabalizer.CNOT(1,4)(state)
Jabalizer.CNOT(1,5)(state)
Jabalizer.CNOT(1,6)(state)
# Display the stabilizer tableau
Jabalizer.update_tableau(state)
tab = Jabalizer.to_tableau(state)
display(tab)
# Convert to graph state
graphState = GraphState(state)
# Display graph adjacency matrix
display(graphState.A)
# Plot graph
Jabalizer.gplot(Jabalizer.Graph(graphState.A))
# Convert back to stabilizer state
stabState = StabilizerState(graphState)
Produces the output:
6×13 Matrix{Int64}:
1 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 0 0 0
0 0 0 0 0 0 1 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 1 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0
6×6 Matrix{Int64}:
0 1 1 1 1 1
1 0 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0
1 0 0 0 0 0
We especially thank Craig Gidney and co-developers for developing the STIM package which provides the CHP backend upon which Jabalizer is based, and especially for implementing some modifications that provided the functionality necessary for this integration. The technical whitepaper for STIM is available here.