CSS Codes
Classical linear codes
Classical error correcting codes were first studied in the 1940s, and many different codes are now known, with the most commonly studied and used codes falling into a category of codes known as linear codes. We'll see exactly what the word "linear" means in this context in just a moment, but a very simple way to express what linear codes are at this point is that they're stabilizer codes that happen to be classical. CSS codes are essentially pairs of classical linear codes that are combined together to create a quantum error correcting code. So, for the sake of the discussion that follows, we're going to need to understand a few basic things about classical linear codes.
Let be the binary alphabet for this entire discussion. When we refer to a classical linear code, we mean a non-empty set of binary strings of length for some positive integer which must satisfy just one basic property: if and are binary strings in then the string is also in Here, refers to the bitwise exclusive-OR of and as we encountered multiple times in the "Fundamentals of quantum algorithms" course.
In essence, when we refer to a classical error correcting code as being linear, we're thinking about binary strings of length as being -dimensional vectors, where the entries are all either or and demanding that the code itself forms a linear subspace. Instead of ordinary vector addition over the real or complex numbers, however, we're using addition modulo which is simply the exclusive-OR. That is, if we have two codewords and meaning that and are binary strings in then modulo 2, which is to say must also be a codeword in Notice, in particular, that this implication must be true even if This implies that must include the all-zero string because the bitwise exclusive-OR of any string with itself is the all-zero string.
Example: the 3-bit repetition code
The 3-bit repetition code is an example of a classical linear code. In particular, we have so, with respect to the linearity condition, there are just two possible choices for and two possible choices for It's a trivial matter to go through the four possible pairs to see that we always get a codeword when we take the bitwise exclusive-OR:
Example: the -Hamming code
Here's another example of a classical linear code called the -Hamming code. It was one of the very first classical error correcting codes ever discovered, and it consists of these 16 binary strings of length 7. (Sometimes the -Hamming code is understood to mean the code with these strings reversed, but we'll take it to be the code containing the strings shown here.)
There is very simple logic behind the selection of these strings, but it's secondary to the lesson and won't be explained here. For now, it's enough to observe that this is a classical linear code: XORing any two of these strings together will always result in another string in the code.
The notation (in single square brackets) means something analogous to the double square bracket notation for stabilizer codes mentioned in the previous lesson, but here it's for classical linear codes. In particular, codewords have bits, we can encode bits using the code (because there are codewords), and it happens to be a distance code, which means that any two distinct codewords must differ in at least positions — so at least bits must be flipped to change one codeword into another. The fact that this is a distance code implies that it can correct for up to one bit-flip error.
Describing classical linear codes
The examples just mentioned are very simple examples of classical linear codes, but even the -Hamming code looks somewhat mysterious when the codewords are simply listed. There are better, more efficient ways to describe classical linear codes, including the following two ways.
-
Generators. One way to describe a classical linear code is with a minimal list of codewords that generates the code, meaning that by taking all of the possible subsets of these codewords and XORing them together, we get the entire code.
In greater detail, the strings generate the classical linear code if
with the understanding that when and when and we say that this list is minimal if removing one of the strings generates a smaller code. A natural way to think about such a description is that the collection forms a basis for as a subspace, where we're thinking about strings as vectors with binary-valued entries, keeping in mind that we're working in a vector space where arithmetic is done modulo
-
Parity checks. Another natural way to describe a classical linear code is by parity checks — meaning a minimal list of binary strings for which the strings in the code are precisely the ones whose binary dot product with every one of these parity check strings is zero. (Similar to the bitwise exclusive-OR, the binary dot product appeared several times in "Fundamentals of quantum algorithms.")
That is, the strings are parity check strings for the classical linear code if
and this set of strings is minimal if removing one results in a larger code. These are called parity check strings because has binary dot product equal to zero with if and only if the bits of in positions where has 1s have even parity. So, to determine if a string is in the code it suffices to check the parity of certain subsets of the bits of
An important thing to notice here is that the binary dot product is not an inner product in a formal sense. In particular, when two strings have binary dot product equal to zero, it doesn't mean that they're orthogonal in the usual way we think about orthogonality. For example, the binary dot product of the string with itself is zero — so it is possible that a parity check string for a classical linear code is itself in the code.
Classical linear codes over the binary alphabet always include a number of strings that's a power of — and for a single classical linear code described in the two different ways just described, it will always be the case that In particular, if we have a minimal set of generators, then the code encodes bits and we'll necessarily have codewords; and if we have a minimal set of parity check strings, then we'll have codewords. So, each generator doubles the size of the code space while each parity check string halves the size of the code space.
For example, the 3-bit repetition code is a linear code, so it can be described in both of these ways. In particular, there's only one choice for a generator that works: We can alternatively describe the code with two parity check strings, such as and — which should look familiar from our previous discussions of this code — or we could instead take the parity check strings to be and or and (Generators and parity check strings are generally not unique for a given classical linear code.)
For a second example, consider the -Hamming code. Here's one choice for a list of generators that works.
And here's a choice for a list of parity checks for this code.
Here, by the way, we see that all of our parity check strings are themselves in the code.
One final remark about classical linear codes, which connects them to the stabilizer formalism, is that parity check strings are equivalent to stabilizer generators that only consist of and identity Pauli matrices. For instance, the parity check strings and for the 3-bit repetition code correspond precisely to the stabilizer generators and which is consistent with the discussions of Pauli observables from the previous lesson.
Definition of CSS codes
CSS codes are stabilizer codes obtained by combining together certain pairs of classical linear codes. This doesn't work for two arbitrary classical linear codes — the two codes must have a certain relationship. Nevertheless, this construction opens up many possibilities for quantum error correcting codes, based in part on over 75 years of classical coding theory.
In the stabilizer formalism, stabilizer generators containing only and identity Pauli matrices are equivalent to parity checks, as we just observed for the 3-bit repetition code. For another example, consider the following parity check strings for the -Hamming code.
These parity check strings correspond to the following stabilizer generators (written without tensor product symbols), which we obtain by replacing each by a and each by an These are three of the six stabilizer generators for the 7-qubit Steane code.
Let us give the name stabilizer generators to stabilizer generators like this, meaning that they only have Pauli and identity tensor factors — so and Pauli matrices never occur in stabilizer generators.
We can also consider stabilizer generators where only and identity Pauli matrices appear as tensor factors. Stabilizer generators like this can be viewed as being analogous to -stabilizer generators, except that they describe parity checks in the basis rather than the standard basis. Stabilizer generators of this form are called stabilizer generators — so no or Pauli matrices are allowed this time.
For example, consider the remaining three stabilizer generators from the 7-qubit Steane code.
They follow exactly the same pattern from the -Hamming code as the -stabilizer generators, except this time we substitute for rather than What we obtain from just these three stabilizer generators is a code that includes the 16 states shown here, which we get by applying Hadamard operations to the standard basis states that correspond to the strings in the -Hamming code. (Of course, the code space for this code also includes linear combinations of these states.)
We can now define CSS codes in very simple terms.
Definition. A CSS code is a stabilizer code that can be expressed using only and stabilizer generators.
That is, CSS codes are stabilizer codes for which we have stabilizer generators in which no Pauli matrices appear, and for which and never appear in the same stabilizer generator.
To be clear, by this definition, a CSS code is one for which it is possible to choose just and stabilizer generators — but we must keep in mind that there is freedom in how we choose stabilizer generators for stabilizer codes. Thus, there will generally be different choices for the stabilizer generators of a CSS code that don't happen to be or stabilizer generators (in addition to at least one choice for which they are).
Here's a very simple example of a CSS code that includes both a stabilizer generator and an stabilizer generator:
It's clear that this is a CSS code, because the first stabilizer generator is a stabilizer generator and the second is an stabilizer generator. Of course, a CSS code must also be a valid stabilizer code — meaning that the stabilizer generators must commute, form a minimal generating set, and fix at least one quantum state vector. These requirements happen to be simple to observe for this code. As we noted in the previous lesson, the code space for this code is the one-dimensional space spanned by the Bell state. The fact that both stabilizer generators fix this state is apparent by considering the following two expressions of an e-bit, together with an interpretation of these stabilizer generators as parity checks in the and bases.
The 7-qubit Steane code is another example of a CSS code.
Here we have three stabilizer generators and three stabilizer generators, and we've already verified that this is a valid stabilizer code.
And the 9-qubit Shor code is another example.
This time we have six stabilizer generators and just two stabilizer generators. This is fine, there doesn't need to be a balance or a symmetry between the two types of generators (though there often is).
Once again, it is critical that CSS codes are valid stabilizer codes, and in particular each stabilizer generator must commute with each stabilizer generator. So, not every collection of and stabilizer generators defines a valid CSS code.
Error detection and correction
With regard to error detection and correction, CSS codes in general have a similar characteristic to the 9-qubit Shor code, which is that and errors can be detected and corrected completely independently; the stabilizer generators describe a code that protects against bit flips, and the stabilizer generators describe a code that independently protects against phase flips. This works because stabilizer generators necessarily commute with errors, as well as operations that are applied as corrections, so they're completely oblivious to both, and likewise for stabilizer generators, errors, and corrections.
As an example, let's consider the 7-qubit Steane code.
The basic idea for this code is now apparent: it's a -Hamming code for bit-flip errors and a -Hamming code for phase-flip errors. The fact that the and stabilizer generators commute is perhaps good fortune, for this wouldn't be a valid stabilizer code if they didn't. But there are, in fact, many known examples of classical linear codes that yield a valid stabilizer code when used in a similar way.
In general, suppose we have a CSS code for which the stabilizer generators allow for the correction of up to bit-flip errors, and the stabilizer generators allow for the correction of up to phase-flip errors. For example, and for the Steane code, given that the -Hamming code can correct one bit flip. It then follows, by the discretization of errors, that this CSS code can correct for any error on a number of qubits up to the minimum of and This is because, when the syndrome is measured, an arbitrary error on this number of qubits effectively collapses probabilistically into some combination of errors, errors, or both — and then the errors and errors are detected and corrected independently.
In summary, provided that we have two classical linear codes (or two copies of a single classical linear code) that are compatible, in that they define and stabilizer generators that commute, the CSS code we obtain by combining them inherits the error correction properties of those two codes, in the sense just described.
Notice that there is a price to be paid though, which is that we can't encode as many qubits as we could bits with the two classical codes. This is because the total number of stabilizer generators for the CSS code is the sum of the number of parity checks for the two classical linear codes, and each stabilizer generator cuts the dimension of the code space in half. For example, the -Hamming code allows for the encoding of four classical bits, because we have just three parity check strings for this code, whereas the 7-qubit Steane code only encodes one qubit, because it has six stabilizer generators.
Code spaces of CSS codes
The last thing we'll do in this discussion of CSS codes is to consider the code spaces of these codes. This will give us an opportunity to examine in greater detail the relationship that must hold between two classical linear codes in order for them to be compatible, in the sense that they can be combined together to form a CSS code.
Consider any CSS code on qubits, and let be the -bit parity check strings that correspond to the stabilizer generators of this code. This means that the classical linear code described by just the stabilizer generators, which we'll name takes the following form.
In words, the classical linear code contains every string whose binary dot product with every one of the parity check strings is zero.
Along similar lines, let us take to be the -bit parity check strings corresponding to the stabilizer generators of our code. Thus, the classical linear code corresponding to the stabilizer generators takes this form.
The stabilizer generators alone therefore describe a code that's similar to this code, but in the basis rather than the standard basis.
Now we'll introduce two new classical linear codes that are derived from the same choices of strings, and but where we take these strings as generators rather than parity check strings. In particular, we obtain these two codes.
These are known as the dual codes of the codes defined previously: is the dual code of and is the dual code of It may not be clear at this point why these dual codes are relevant, but they turn out to be quite relevant for multiple reasons, including the two reasons explained in the following paragraphs.
First, the conditions that must hold for two classical linear codes and to be compatible, in the sense that they can be paired together to form a CSS code, can be described in simple terms by referring to the dual codes. Specifically, it must be that or equivalently, that In words, the dual code includes the strings corresponding to stabilizer generators, and their containment in is equivalent to the binary dot product of each of these strings with the ones corresponding to the stabilizer generators being zero. That, in turn, is equivalent to each stabilizer generator commuting with each stabilizer generator. Alternatively, by reversing the roles of the and stabilizer generators and starting from the containment we can reach the same conclusion.
Second, by referring to the dual codes, we can easily describe the code spaces of a given CSS code. In particular, the code space is spanned by vectors of the following form.
In words, these vectors are uniform superpositions over the strings in the dual code of the code corresponding to the stabilizer generators, shifted by (in other words, bitwise XORed with) strings in the code corresponding to the stabilizer generators. To be clear, different choices for the shift — represented by the string in this expression — can result in the same vector. So, these states aren't all distinct, but collectively they span the entire code space.
Here's an intuitive explanation for why such vectors are both in the code space and span it. Consider the -qubit standard basis state for some arbitrary -bit string and suppose that we project this state onto the code space. That is to say, letting denote the projection onto the code space of our CSS code, consider the vector There are two cases:
-
Case 1: This implies that each stabilizer generator of our CSS code acts trivially on The stabilizer generators, on the other hand, each simply flip some of the bits of In particular, for each generator of the stabilizer generator corresponding to transforms into By characterizing the projection as the average over the elements of the stabilizer (as we saw in the previous lesson), we obtain this formula:
-
Case 2: This implies that at least one of the parity checks corresponding to the stabilizer generators fails, which is to say that must be a eigenvector of at least one of the stabilizer generators. The code space of the CSS code is the intersection of the eigenspaces of the stabilizer generators. So, as a eigenvector of at least one of the stabilizer generators, is therefore orthogonal to the code space:
And now, as we range over all -bit strings discard the ones for which and normalize the remaining ones, we obtain the vectors described previously, which demonstrates that they span the code space.
We can also use the symmetry between and stabilizer generators to describe the code space in a similar but different way. In particular, it is the space spanned by vectors having the following form.
In essence, and have been swapped in each instance in which they appear — but we must also swap the standard basis for the basis, which is why the Hadamard operations are included.
As an example, let us consider the 7-qubit Steane code. The parity check strings for both the and stabilizer generators are the same: and The codes and are therefore the same; both are equal to the -Hamming code.
The dual codes and are therefore also the same. We have three generators, so we obtain eight strings.
These strings are all contained in the -Hamming code, and so the CSS condition is satisfied: or equivalently,
Given that contains half of all of the strings in there are only two different vectors that can be obtained by choosing This is expected, because the 7-qubit Steane code has a two-dimensional code space. We can use the two states we obtain in this way to encode the logical state and as follows.
As usual, this choice isn't forced on us — we're free to use the code space to encode qubits however we choose. This encoding is, however, consistent with the example of an encoding circuit for the 7-qubit Steane code in the previous lesson.