QEC 101 Lab 7: qLDPC Codes
One of the most promising classes of QEC codes are so called quantum low density parity check (qLDPC) codes. These codes are quite general and include well known codes like the surface code. This lab will walk through the basics of classical LDPC codes, the challenges that arise when moving to qLDPC codes, and how to construct valid qLDPC codes with favorable properties. You will eventually implement techniques from "Lift-Connected Surface Codes" connecting what you have leaned to state-of-the-art research.
Prerequisites: This lab assumes you have a moderate knowledge of QEC and have completed the core QEC 101 courses (labs 1-4), especially the labs covering stabilizers and decoders.
The list below outlines what you'll be doing in each section of this lab:
7.1 Learn the basics of classical LDPC codes and how to analyze their properties.
7.2 Learn why quantum LDPC codes are challenging to construct and how to build hypergraph product (HGP) codes.
7.3 Extend the HGP procedure to produce larger qLDPC codes with improved properties.
7.4 Compare the quality of the codes you created using the NVIDIA BP+OSD decoder.
Terminology you will use:
low density parity check, encoding rate, degree
hypergraph product
lifted product
circulants
qLDPC codes have a number of favorable properties that make them promising for deployment within nearer term fault tolerant workflows.
First run the cell below to prepare the necessary libraries.
7.1 Classical LDPC Codes
Robert Gallager first conceived of low density parity check (LDPC) codes in his 1960 MIT dissertation but it was underappreciated at the time and interest resurged in the 90's as other error correction codes rose in prominence. LDPC codes are now used widely in telecommunications and computer memory applications
An LDPC code is a classical parity check error correction code with a sparse parity check matrix . The parity check matrix is often represented by a Tanner graph, which was introduced in lab 4 on decoders. A Tanner graph is drawn with check nodes on the top row and variable nodes on the bottom. The Tanner graph for the Steane code is shown below.

A sparse means that each variable and check node only connects to a limited number of other nodes. The variable node degree characterizes the maximum number of checks any (q)bit is involved in while the and check node degree characterizes the maximum number of (q)bits involved in any given check. Ideally, these two values are as small as possible to maintain low density.
A second important property is the encoding rate ().
Where, is the number of encoded logical bits, is the number of data bits, and is the number of check bits. A high encoding rate is good and means that many logical bits can be encoded with a lower overhead. However, this competes with other properties like the code distance - i.e. the ability to correctly capture errors.
What is depends on the number of linearly independent constraints. To determine this, perform Gaussian elimination over GF(2). GF(2) comes from the world of abstract algebra and corresponds to a field of two elements. Essentially, this just means integer math governed by mod 2 arithmetic. The Gaussian elimination result can be used to determine rank() which is related to by
A final characteristic of a desirable LDPC code is how suited it is for decoding. Common decoders like belief propagation (BP) can struggle when the Tanner graph has 4-cycles. These form local loops (see image below) which can make it hard for the decoder to converge to a solution.

In most cases, it turns out that LDPC codes are very easy to generate. Random generation of usually produces a good LDPC code. This also provides flexibility as new codes can be generated as needed depending on the problem at hand. Randomly generated codes also perform well and produce results close to the Shannon limit, that is the theoretical maximum of information that can pass through a noisy channel.
Exercise 1:
Given the three parity check matrices below, write a function to analyze them and determine the check and variable node degrees, the encoding rate, the indices of any four cycles, and if any nodes are unchecked.
7.2 Quantum LDPC
qLDPC codes have many similarities to their classical counterparts, particularly with respect to terms like encoding rate and degree. Unfortunately, a major difference is that valid qLDPC codes with favorable properties cannot be produced by randomly generating parity check matrices. This is because the and parity check matrices ( and ) must commute () for a valid CSS code that can correct both types of errors.
The probability of randomly producing parity check matrices that commute is vanishingly small, let alone exhibit favorable properties. Cutting edge research focused on qLDPC codes is determined to find clever ways to produce quality parity check matrices that meet these constraints.
One particularly insightful approach is using so called hypergraph product codes. The idea is to take two "good" ( in this case a technical term meaning the codes distance scales as ) classical parity check matrices () and () and combine them in such a way that and commute (i.e. ) and the resulting codes have a constant encoding rate and a distance that scales proportionally to the square root of the number of data qubits.
The procedure works by defining the final parity check matrix as a block encoding of and .
Each quantum parity check matrix is then defined in terms of the the two classical base matrices.
This construction ensures that and commute. The proof is as follows:
It may not be clear at first why the final term equals zero. Recall that all operations with parity check matrices occur mod 2. So, taking any binary matrix and multiplying it by 2, will make every entry 0 or 2 = 0 mod 2.
Exercise 2:
Construct a hypergraph product code using a pair of three-qubit repetition code base matrices. That is, begin with:
Build the parity check matrices for and and confim they commute. Note: the galois package is used to define the matrices over a Galois field (GF2), which ensures modular arithmetic is baked in to your computations. All operations can be performed just like you would with numpy.
It turns out there is a nice visual interpretation of the hypergraph product code you just generated if the Tanner graphs form a multiplication table of sorts. Each node of the product tanner graph that is the product of a check qubit with a check qubit or a data qubit with a data qubit produces a data qubit. If the top Tanner graph is a circle (data qubit) and the left Tanner graph a square (check qubit), the result is an stabilizer check. Likewise, if the top Tanner graph is a square and the left Tanner graph a circle, the result is a parity check, producing the tanner graph below. Does it look familiar?

Remarkably, it turns out the product of two size classical repetition codes is a [[ , , ]] surface code! This is a great example demonstrating how two very simple classical codes can construct a more sophisticated quantum code which obeys the required commutativity constraints.
7.3 Generalizing HGP - Lifted Product Codes
It is possible to build upon the HGP method in a more general manner where products are taken between two parity check matrices that have non-integer entries. Such an approach is called a lifted product (LP) as the elements of the parity check matrix are "lifted" to higher order elements. LP codes can often retain the degree of checks and provide higher distance codes with a smaller qubit overhead.
A LP construction still needs to ensure that holds as parity check matrices are modified to have non-integer elements. One way to ensure this is to replace parity check matrix elements with a commutative matrix ring, that is, a set of mathematical objects with properties that ensure multiplication of any elements commute, ensuring remains true (see the second term in the original proof of commutativity a few cells above). One example is circulant matrices which are defined as:
Where are cyclic permutation matrices that shift columns of the identity matrix by spaces to the right and where can be either 0 or 1. The notation indicates the binary representation of matrix size .
Exercise 3:
Build the following binary matrix representations:
A LP code is built by taking a HGP of two parity check matrices where each 1 is, in this case, a circulant matrix . A LP code of size will increase the number of qubits and checks by a factor of L. This is because each entry in the parity check matrix is "lifted" and replaced by a set of checks and qubits.
The same HGP equations from the previous section hold, but instead, the parity check matrices are denoted with a tilde to note that their elements are circulants where each entry is otherwise a 1. That is to say,
The figure below, based on figure 2 of Lift-Connected Surface Codes, is helpful for understanding what the LP construction is doing. The overall procedure is similar. First, the base matrices are selected and are used in the same HGP procedure you did previously to form and . Then, each 1 in each parity check matrix is replaced with a circulant . This simple swap takes select connections from the original Tanner graph, and lifts it to be replaced with a set of check and data qubits.

If is simply the identity matrix , the resulting LP codes is the result of the HGP code duplicated trivially times. Adding permutations to such as adds non-trivial checks between the HGP code copies. Notice the figure below (adapted figure 3 from Lift-Connected Surface Codes) begins with the HGP that you performed earlier. Then, The LP construction creates four copies of the surface code and interconnects them with parity checks.

It turns out that the LP surface code is a [[52,4,4]] code whereas four copies of the surface code would be [[52,4,3]]. This means that the encoding rate is the same, but the code distance improves thanks to the LP procedure. These sorts of clever constructions are driving qLDPC code research to continually improve code properties while maintaining the commutativity properties.
Generally speaking, a LP surface code is parameterized with and , where is the size of the base repetition code and is the number of copies produced by the lift procedure.
Exercise 4:
Build the [[52,4,4]] ( and ) LP surface code by performing the following steps. First, use the base matrix below which can be conveniently split into , which produces trivial copies of the surface code and (), which interacts these surface code copies.
To produce the [[52,4,4]] code, we can perform the HGP procedure twice using and . Lifting the first with and the second with and summing the results will produce the parity check matrices for the [[52,4,4]] code.
Modify your HGP function to lift Hx_a and Hz_a with an arbitrary and Hx_b and Hz_b with the transpose of .
Then build the [[52,4,4]] code by lifting H_copy and H_int (defined below) with and , respectively. Confirm that Hz and Hx of the final result commute.
Now, analyze the Hz and Hx parity check matrices to 1) make sure they commute and 2) confirm the degrees are as expected. Each stabilizer should act on maximum 6 qubits and each qubit should be involved in no more than 6 checks (summing Z and X checks as the full parity check matrix would be a concatenation of both and .).
7.4 Decoding with CUDA-Q QEC
💻 Just a heads-up: This notebook is designed to be run on an environment with a GPU. If you don't have access to a GPU, feel free to read through the cells and explore the content without executing them. Enjoy learning! ⭐
qLDPC codes are well suited for decoding with CUDA-Q's accelerated BP+OSD decoder found in the CUDA-Q QEC library. If you want to learn more about BP+OSD decoding, complete lab 4 on decoding.
As we have not discussed logical observables for these codes, the code below will randomly generate an error vector with a 5% chance of an error on each qubit (Only assuming bit flip errors for now). The decoder will produce a logical error if the decoder cannot identify all of the errors given the syndrome. However, note that each of these errors might not produce a logical flip in practice, so this considers a worst case scenario.
In the cell below, run the decoder using the matrix you produced for the [[52,4,4]] LP surface code. Carefully read the code and see if you can spot where errors and syndromes are generated, where decoder options are specified, and how the decoder is called. Run the code and note what the logical error rate is.
Now, run the same code but use the Hz_lifted_copy parity check matrix. This code is simply four non-interacting copies of the surface code and hence a [[52,4,3]] code. How does the logical error rate compare? Can you see the benefit of the LP surface code as it adds one to the distance and outperforms copies of the surface code significantly.
Each choice of and will produce a different LP surface code. It varies case by case if the LP approach is better than copies of the surface code. Examine the table below from Lift-Connected Surface Codes where the code parameters were obtained via numerical simulation. Note, how the entries highlighted in green are cases where the LP construction results (top entry) in a code with the same overhead but a higher code distance compared to surface code copies (bottom entry).

Summary
You now have a foundational understanding of qLDPC codes and how they differ from their classical counterparts. qLDPC codes are quite promising and will continue to be an active field of research. The methods covered in this work are just a sample of the different ways to construct qLDPC code parity check matrices yet lay the groundwork for you to understand other state of the art techniques like bivariate bicycle codes.