ABSTRACT (original article): We introduce an open source software package UniversalQCompiler written in Mathematica that allows the decomposition of arbitrary quantum operations into a sequence of single-qubit rotations (with arbitrary rotation angles) and controlled-NOT (C-NOT) gates. Together with the existing package QI, this allows quantum information protocols to be analysed and then compiled to quantum circuits. Our decompositions are based on Phys. Rev. A 93, 032318 (2016), and hence, for generic operations, they are near optimal in terms of the number of gates required. UniversalQCompiler allows the compilation of any isometry (in particular, it can be used for unitaries and state preparation), quantum channel, positive-operator valued measure (POVM) or quantum instrument, although the run time becomes prohibitive for large numbers of qubits. The resulting circuits can be displayed graphically within Mathematica or exported to LaTeX. We also provide functionality to translate the circuits to OpenQASM, the quantum assembly language used, for instance, by the IBM Q Experience. CITATION (original article): Raban Iten, Oliver Reardon-Smith, Emanuel Malvetti, Luca Mondada, Gabrielle Pauvert, Ethan Redmond, Ravjot Singh Kohli, Roger Colbeck (2021), Introduction to UniversalQCompiler, arXiv:1904.01072. https://doi.org/10.48550/arXiv.1904.01072
GitHub: https://github.com/Q-Compiler/UniversalQCompiler
GitHub: https://github.com/Q-Compiler/UniversalQCompiler
UniversalQCompiler provides a Mathematica package that allows to decompose generic quantum computations into sequences of C-NOT gates and arbitrary single-qubit rotations. In particular, the package allows for the following:
◼
Decomposing isometries from m to n qubits, and hence, in particular decomposing arbitrary unitaries on m qubits and to do state preparation
◼
Decomposing quantum channels from m to n qubits
◼
Decomposing POVMs on m qubits
◼
Simplifying gate sequences
◼
Drawing quantum circuits within Mathematica
◼
Exporting quantum circuits to LATEX
◼
Running quantum circuits on the IBM Q Experience (using the OpenQASM converter)
◼
Compilation for trapped ions, i.e., converting between gate sequences using CNOT (and single-qubit rotation) to those that use Molmer-Sorensen gates
A detailed documentation of the Mathematica package can be found on our webpage. The notebook Examples.nb helps the user to get started quickly and provides a short overview over the methods provided by UniversalQCompiler.
This project also contains a converter (based on ProjectQ) to translate gate sequences from the Mathematica package UniversalQCompiler to OpenQASM, the quantum assembly language used, for instance, by the IBM Q Experience.
Moreover, we provide bindings to directly link Python to Mathematica. This is however provided without any guarantees or support in the directory UNSTABLE
This project also contains a converter (based on ProjectQ) to translate gate sequences from the Mathematica package UniversalQCompiler to OpenQASM, the quantum assembly language used, for instance, by the IBM Q Experience.
Moreover, we provide bindings to directly link Python to Mathematica. This is however provided without any guarantees or support in the directory UNSTABLE
Overview
Overview
The diagram at the top indicates how the Mathematica packages QI and UniversalQCompiler can be used to analyse quantum information protocols for running on some quantum hardware.
Getting started
Getting started
To use our Mathematica package UniversalQCompiler.m, you need to have installed Wolfram Mathematica (we tested the package for Mathematica 11.1 and 11.3). The code relies on the package QI.m which can be downloaded from https://github.com/rogercolbeck/QI. The package can then be loaded in any Mathematica notebook (see our documentation for more details).
Note that the Makefile is only used for the unstable bindings to Python. You do not need any Makefile for the Mathematica package or the QASM converter.
Basic Gate types
Basic Gate types
This package decomposes arbitrary gates into a sequence of CNOTs and single qubit rotations. The latter are expressed using the convention that an rotation by angle t about the x-axis of the Bloch sphere is
In[]:=
RxM[t,1]//MatrixForm
Out[]//MatrixForm=
Cos t 2 | Sin t 2 |
Sin t 2 | Cos t 2 |
A y-rotation by angle t is:
In[]:=
RyM[t,1]//MatrixForm
Out[]//MatrixForm=
Cos t 2 | Sin t 2 |
-Sin t 2 | Cos t 2 |
And a z-rotation is
In[]:=
RzM[t,1]//MatrixForm
Out[]//MatrixForm=
t 2 | 0 |
0 | - t 2 |
A CNOT with qubit 1 as the control and 2 as the target is
In[]:=
CNOTM[1,2]//MatrixForm
Out[]//MatrixForm=
1 | 0 | 0 | 0 |
0 | 1 | 0 | 0 |
0 | 0 | 0 | 1 |
0 | 0 | 1 | 0 |
Single-qubit unitaries
Single-qubit unitaries
Choose a random 2x2 unitary and decompose it into a Z rotation, a Y rotation then a Z rotation
u=PickRandomUnitary[2]
{{-0.35917-0.548312,0.536212-0.531815},{-0.184883+0.732235,0.654784+0.0301123}}
gates=ZYZDec[u]
{{3,4.91376,1},{2,1.71197,1},{3,5.45595,1}}
This is the standard form for gate outputs. The first gate in the list is an Rz on qubit 1, etc. We can construct the unitary from these (up to phase) as follows. To get a reminder of the conventions, use GateTypes[]
GateTypes[]
Gate types for UniversalQCompiler
{-2,diag,act}: diagonal gate with entries diag on the qubits listed in act
{-1,n,m}: CZ with qubit n the control and m the target
{0,n,m}: CNOT with qubit n the control and m the target
{1,t,n}: x-rotation by angle t for qubit n
{2,t,n}: y-rotation by angle t for qubit n
{3,t,n}: z-rotation by angle t for qubit n
{4,0,n}: trace out qubit n
{4,1,n}: measure qubit n in the computational basis
{5,0,n}: qubit n starts in state |0>
{5,1,n}: qubit n starts in state |1>
{6,0,n}: qubit n is postselected on |0>
{6,1,n}: qubit n is postselected on |1>
{-10,t,{n,m}}: XX-gate with angle t on qubits n,m
{-11,{t,p},n}: R-gate with angles t,p on qubit n
Confirm the result (note that decompositions are always up to phase)
outu=CreateOperationFromGateList[gates]
{{0.298295-0.583669,0.727634+0.202237},{-0.727634+0.202237,0.298295+0.583669}}
This is equal to u up to phase:
Chop[outu/outu[[1,1]]*u[[1,1]]-u]
{{0,0},{0,0}}
We get the same result from the Quantum Shannon Decomposition
gatelist=QSD[u]
{{3,4.91376,1},{2,1.71197,1},{3,5.45595,1}}
We can also re-express the output in string form
ListFormToStr[gatelist]
{Rz(4.91376)(1),Ry(1.71197)(1),Rz(5.45595)(1)}
Or as matrices
Map[MatrixForm,ListFormToOp[gatelist]]
,
,
-0.774599+0.632452 | 0.+0. |
0.+0. | -0.774599-0.632452 |
0.655477+0. | 0.755216+0. |
-0.755216+0. | 0.655477+0. |
-0.915672+0.401926 | 0.+0. |
0.+0. | -0.915672-0.401926 |
Or draw the topology for it:
PrintCircuit[gatelist]
If you use the package QCircuit in then the command LatexQCircuit can be used to generate the circuit in a compatible form:
L
A
TE
XLatexQCircuit[gatelist]
{& \qw & \gate{R_z} & \gate{R_y} & \gate{R_z} & \qw }
Using the option AnglePrecision2 gives the angles to two significant figures.
PrintCircuit[gatelist,AnglePrecision2]
LatexQCircuit[gatelist,AnglePrecision2]
{& \qw & \gate{R_z(\textnormal{$4.9$})} & \gate{R_y(\textnormal{$1.7$})} & \gate{R_z(\textnormal{$5.5$})} & \qw }
Two qubit unitaries
Two qubit unitaries
Using QSD
Using QSD
Now choose a real two-qubit gate and do the Quantum Shannon Decomposition. The decomposition achieves the minimal number of required CNOT gates for arbitrary (and not necessarily generic) two qubit gates (and is equivalent to calling DecUnitary2Qubits in the considered case).
u=RPickRandomUnitary[4];u//MatrixForm
0.27403 | 0.60353 | 0.0491122 | 0.747159 |
-0.431234 | -0.223208 | 0.826736 | 0.284118 |
0.854943 | -0.229555 | 0.437897 | -0.156918 |
-0.0895389 | 0.730229 | 0.349774 | -0.580006 |
gatelist=QSD[u]
{{3,4.71239,2},{2,1.5708,2},{3,3.04245,2},{3,3.14159,1},{2,2.0275,1},{3,1.5708,1},{0,2,1},{3,5.63206,1},{1,6.02488,1},{1,5.12899,2},{3,3.18062,2},{0,2,1},{2,1.5708,1},{1,1.5708,1},{2,1.5708,2},{3,1.5708,2},{0,1,2},{3,6.28319,2}}
PrintCircuit[gatelist]
We can check the result as before:
We can also apply u to other qubits using the second argument of QSD to specify. E.g. to the second and fourth qubits
Or, reversing the gates to the fourth and second qubits
Using the Knill decomposition
Using the Knill decomposition
We could also use another decomposition
In this case, the output is much longer, but still gives the same result
Using the column by column decomposition
Using the column by column decomposition
The other decomposition we can do is the column-by-column decomposition
Decomposition of isometries from m to n qubits
Decomposition of isometries from m to n qubits
We provide different methods to decompose arbitrary isometries from m to n qubits. Recall that an isometry from m to n qubits corresponds to a unitary operation on n qubits where n-m qubits start in a fixed state |0>.
The method DecIsometry choses automatically the method that achieves the lowest CNOT count. Let’s consider how to decompose a random isometry from one qubit to three qubits.
We can also use CreateOperationFromGateList to directly give the isometry
CNOT counts for different decompositions
CNOT counts for different decompositions
Instead of using DecIsometry, a specific method to decompose an isometry can be chosen (in particular, to lower the run time). Which method is best (and chosen by DecIsometry) depends on the situation
For a full unitary on 4 qubits:
For an isometry from 1 qubit to 4 qubits
For generic isometries, the CNOT count for the column-by-column decomposition can be improved by using a different way to decompose the first column (this may increase the running time for large isometries significantly):
By default simplifications are done automatically. To switch them off use Simp->False. For the considered isometry, this gives the same CNOT count of the column-by-column decomposition, but with more single-qubit rotations.
DecIsometryGeneric automatically picks the method with the lowest CNOT count for a generic isometry (which is the column by column decomposition with the option FirstColumn”StatePreparation” in the considered case).
As an example for an non generic isometry, we consider an isometry of the following simple form:
Note that DecIsometryGeneric doesn’t get the best count here, because it is based on generic isometries, but here we have a special case. DecIsometry recovers the best count.
In the following case the Knill decomposition does best
Again DecIsometryGeneric does not give the best, but DecIsometry does
State preparation
State preparation
State preparation is just a special case of an isometry from m to n qubits, with m=0. We provide a method StatePreparation, which achieves the lowest known CNOT counts for generic states.
Note that one gets the same output calling DecIsometry[state] in the considered case.
This is equal to the state up to phase
Alternatively, one can decompose a state using uniformly controlled gates by calling the column by column decomposition. This requires one CNOT gate more in the considered case (but lowers the running time for large states).
We can also use a special decomposition for sparse states
Dense state preparation is worse:
Analytic calculations
Analytic calculations
We can also do analytic calculations
Print Circuit can also be used to show the output
The option AnglePrecision->1 shows the angles (because they are exact, any precision above 0 can be used)
If non-exact output is desired, can use NGateList
The exact computations rapidly become time consuming
The output matches the original isometry (up to phase)
Generating the operator involves attempts to simplify so can be slow. The option FullSimp->False sometimes yields just as good a result after a final simplification (and can be faster, even including the final simplification):
Using the option Simp->False can be faster (but gives a longer sequence):
By comparison, the numerical version is almost instantaneous
Again, the output matches:
Using the Knill decomposition for analytic calculations
Using the Knill decomposition for analytic calculations
The Knill decomposition is not good at handling analytic calculations at present. However, unitaries of a very simple form can be decomposed within a reasonable time.
Sparse states analytically
Sparse states analytically
For sparse states we can generate an exact one using FPickRandomSparsePsi
Decomposing channels
Decomposing channels
We can also decompose channels. Take a channel from 1 qubit to 2 qubits with 10 Kraus operators
Check that it is a valid channel
Its action on a density operator rho is
This channel has more than the maximum number of Kraus operators, so we can compress it to a smaller representation of the same channel
The action on rho is the same:
The output is quite long, but the first and last 20 gates are displayed below. Note the trace out circuit elements, and the indication of ancilla.
We can reconstruct the channel as follows.
First remove the traces from the gatelist
We have a channel from 1 to 2 qubits, so the first 4 qubits of the input start in state 0. The partial traces can be used to generate Kraus operators by taking the projectors onto the computational basis:
Check that it has the same action
We can also use CreateOperationFromGateList
Decomposing POVMs
Decomposing POVMs
Similarly we can implement a POVM. Choose a random POVM on 1 qubit with 3 elements
Check that it is a valid POVM: its elements should sum to identity and all operators should be positive
We now decompose it into a list of gates
Printing the last part of the circuit shows the measured qubits
To get back the POVM from the gatelist:
The zero POVM element can be dropped. We then get the same POVM as we started with
We could also use CreatePOVMFromGateList
CreatePOVMFromGateList automatically removes zero POVM elements if they occur at the end of the list of POVM elements. To avoid this, use the option DropZero->”None”.
The option DropZero->”All” removes all POVM elements. Note that this can make it difficult to identify POVM elements with outcomes (in the case where zero elements are in the middle of the list of POVM elements).
Constructing circuits
Constructing circuits
We can also build our own circuits and use the code to simplify them
We could also simplify the gate sequence analytically, by calling SimplifyGateList[gatelist]]. But this takes much longer:
For simple constructions, ColumnByColumnDec is often best
We can also generate quantum instruments
We can also generate quantum instruments
If we both trace out and measure, we get a quantum instrument
Each part of this should be a trace decreasing completely positive map such that the combined channel is trace preserving:
If we care about the measurement, we can instead construct the POVM
These agree with the channels
The following command provides a convenient way to see the action of an instrument:
We can also generate random instruments. The following gives an instrument from 1 qubit to 2 qubits comprising two channels each with 4 Kraus operators
The start of the circuit is shown below
And here is the end of the circuit
To get back the instrument
To check these are the same instrument we can extract the individual channels and confirm that they have the same Choi states:
We can also observe the same action on a randomly chosen input
To generate an instrument from 1 qubit to 2 comprising three channels with 1, 2 and 3 Kraus operators, use
Random circuits can be constructed for isomteries
Random circuits can be constructed for isomteries
To generate a random circuit for an isometry from 1 qubit to 2 qubits with 4 CNOTs. Note that after each CNOT there are 4 rotations, and at the start of the circuit there are also rotations.
With TotGates->True this generates an isometry with the total number of gates, rather than the number of CNOTs
CITE THIS NOTEBOOK
CITE THIS NOTEBOOK
UniversalQCompiler - an opensource software package for decomposing generic quantum computations
by Raban Iten, Oliver Reardon-Smith, Emanuel Malvetti, Luca Mondada, Gabrielle Pauvert, Ethan Redmond, Ravjot Singh Kohli, Roger Colbeck
Wolfram Community, STAFF PICKS, November 14, 2024
https://community.wolfram.com/groups/-/m/t/3320494
by Raban Iten, Oliver Reardon-Smith, Emanuel Malvetti, Luca Mondada, Gabrielle Pauvert, Ethan Redmond, Ravjot Singh Kohli, Roger Colbeck
Wolfram Community, STAFF PICKS, November 14, 2024
https://community.wolfram.com/groups/-/m/t/3320494