Tutorials¶
These set of tutorials provide more insight in the workings of LibKet for different commonly used quantum circuits, backends and advanced operations. All tutorial code can be found in the LibKet examples folder. If not mentioned otherwise, all expressions are evaluated for 1024 shots on all active backends. This section is complemantary material to the example code and as such the tutorials are best followed with code and documenation side to side.
Tutorial 1: Bell state
This tutorial shows how to create a simple LibKet expression, the Bell circuit.
Tutorial 2: Quantum Teleportation
This tutorial implements the quantum teleportation circuit, which teleports the state of the first qubit to the third qubit by using measurements taken from the first two qubits.
Tutorial 3: Advanced
This tutorial shows the use of more advanced filters and gates to create this arbitrary circuit. The circuit itselfs serves no real purpose, but is rather an example of how LibKet handles filters and gate functors.
Tutorial 4: Static_for with graph
This tutorial shows how to implement the static_for
function in combination with the LibKet graph class. Here the static_for
loop is used to apply a cnot gate between every connected node in the graph. The ring graph with five nodes is represented as a list of edges. From this, it follows that the static_for loop should iterate over all edges in this list and apply a cnot function between two nodes that are connected, where the first node is the control and the second node the target qubit.
Tutorial 5: QPU execution
In this tutorial, three methods of retrieving QPU results are shown:
Asynchronous execution
Synchronous execution
Evaluation
Both asynchronous and synchrounous execution return a pointer to the quantum job. The asynchronous option does not interrupt the code exection and the QPU execution will run in the background, so you can run code while the quantum expression is being evaluated. The synchronous option waits until the QPU has finished evaluating the quantum expression before contuing with the main code. For both methods, results can be retreived using the job->get()
function.
The evaluation method is similar to the sychronous execution, but directly returns results in JSON format instead of the QObj
pointer. The circuit belows shows the simple quantum expression used in this tutorial:
Tutorial 6: Quantum Fourier Transform
Here, the LibKet circuit QFT is used to construct a QFT circuit with allswap at the end. The Quantum Fourier Tranform. More information on the QFT can be found here. The inverse QFT can be applied by using the QFTdag()
circuit.
Tutorial 7: Arbitrary Control Circuit
The following circuit implements the arbitrary control circuit. It takes four parameters: A controlled binary gate, a filter for the control qubits, a filter for the ancilla qubits and a filter for the target qubit. This example implements a 4-qubit controlled X-gate. The first four qubits are used a control for the target qubit \(q_4\). For every \(N\) control qubits, \(N-1\) ancilla qubits are needed, in this case the last three qubits.
Tutorial 8: Allswap
The Allswap circuit creates a quantum expression where the qubit order in a given selection is flipped.
Tutorial 9: QAOA
This tutorial shows the implementation of a QAOA circuit for the Maximum Cut problem on arbitrary graph. More information on the QAOA can be found here. This toturial shows some more advance use of the static_for()
function. The circuit is constructed for a singe QAOA iteration (\(p=1\)). This tutorial only shows how to create the QAOA circuit. For the QAOA to function, an classical optimizer is needed to optimize parameters \(\beta\) and \(\gamma\).
Tutorial 10: Hook
This tutorial illustrates the usage of the hook gate, which is able to reference another LibKet expression or create an expression from a cQASM string.
Tutorial 11: Just-In-Time Compilation
Using Just-In-Time Compilation, LibKet is able to use command line inputs for compile-time expresions. In this tutorial, a LibKet expression can be entered via the command line and will be processed later on in program.
Tutorial 12: Execution Scripts
he optional ftor_init
, ftor_before
, and ftor_after
make it possible to inject user-defined code at three different locations of the execution process. In this tutorial, a simple statement after the execution collects the histogram data of the experiment using Qiskit’s get_count()
function, generates a histogram plot and saves it to a file named ‘histogram.png’ in the build folder.
The init script imports the necessary packages for the qiksit visualization. After execution, the after script gets the counts and plots the histogram. It should be noted that the code injections are idented automatically and must not have trailing \t
’s. Each line must end with \n
.
Tutorial 13: Unitary decomposition
This tutorial illustrates the basic usage of the built-in decomposition of a controlled 2x2 unitary gate into native gates. The unitary gate accepts an arbitrary 2x2 unitary matrix \(U\) as input and performs the ZYZ decomposition of \(U\). For example the following unitary matrix is used:
The decomposition created the following quantum circuit:
Tutorial 14: Controlled unitary decomposition
This tutorial implementes the controlled unitary decomposition, which is similar the the previous tutorial on the decomposed unitary. In this case, a control qubit is incluced to form a binary gate which controls the rotations of the unitary. For example the following unitary matrix is used:
The controlled decomposition created the following quantum circuit:
Tutorial 15: Quantum Program
The quantum program allows for a linear approach to constructing a quantum expression, as often seen in QASM languages. Here, qubit gates and operations are added sequantially and are translated to a quantum expression.
Tutorial 16: HHL Algorithm
This tutorial shows the implementation of the Harrow-Hassidim-Lloyd (HHL) algorithm (see link). This algorithm is used to solve Linear systems of the form:
where A is an \(N_{b}×N_{b}\) Hermitian matrix and \(\vec{x}\) and \(\vec{b}\) are \(N_b\)-dimensional vectors. In this example, \(A\) and \(\vec{b}\) are set to:
The controlled unitary evolution is computed to be:
Which results in the following circuit example:
The output result indeed confirms the expected ratio found in the HHL paper, which should be around \(prob(b_0)\) : \(prob(b_1)\) = 1 : 9.