Skip to main content
IBM Quantum Platform

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 Σ\Sigma be the binary alphabet for this entire discussion. When we refer to a classical linear code, we mean a non-empty set CΣn\mathcal{C}\subseteq\Sigma^n of binary strings of length n,n, for some positive integer n,n, which must satisfy just one basic property: if uu and vv are binary strings in C,\mathcal{C}, then the string uvu\oplus v is also in C.\mathcal{C}. Here, uvu\oplus v refers to the bitwise exclusive-OR of uu and v,v, 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 nn as being nn-dimensional vectors, where the entries are all either 00 or 1,1, 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 2,2, which is simply the exclusive-OR. That is, if we have two codewords uu and v,v, meaning that uu and vv are binary strings in C,\mathcal{C}, then u+vu + v modulo 2, which is to say uv,u\oplus v, must also be a codeword in C.\mathcal{C}. Notice, in particular, that this implication must be true even if u=v.u = v. This implies that C\mathcal{C} must include the all-zero string 0n,0^n, 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 C={000,111},\mathcal{C} = \{000,111\}, so, with respect to the linearity condition, there are just two possible choices for uu and two possible choices for v.v. 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:

000000=000,000111=111,111000=111,111111=000.000 \oplus 000 = 000, \quad 000 \oplus 111 = 111, \quad 111 \oplus 000 = 111, \quad 111 \oplus 111 = 000.

Example: the [7,4,3][7,4,3]-Hamming code

Here's another example of a classical linear code called the [7,4,3][7,4,3]-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 [7,4,3][7,4,3]-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.)

0000000110000110100100110011011010010101011100110000011111110000011001010101010010111001100010110100111101111111\begin{array}{cccc} 0000000 & 1100001 & 1010010 & 0110011\\[1mm] 0110100 & 1010101 & 1100110 & 0000111\\[1mm] 1111000 & 0011001 & 0101010 & 1001011\\[1mm] 1001100 & 0101101 & 0011110 & 1111111 \end{array}

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 [7,4,3][7,4,3] (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 77 bits, we can encode 44 bits using the code (because there are 16=2416 = 2^4 codewords), and it happens to be a distance 33 code, which means that any two distinct codewords must differ in at least 33 positions — so at least 33 bits must be flipped to change one codeword into another. The fact that this is a distance 33 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 [7,4,3][7,4,3]-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.

  1. 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 u1,,umΣnu_1,\ldots,u_m\in\Sigma^n generate the classical linear code C\mathcal{C} if

    C={α1u1αmum:α1,,αm{0,1}},\mathcal{C} = \bigl\{\alpha_1 u_1 \oplus \cdots \oplus \alpha_m u_m\,:\,\alpha_1,\ldots,\alpha_m\in\{0,1\}\bigr\},

    with the understanding that αu=u\alpha u = u when α=1\alpha = 1 and αu=0n\alpha u = 0^n when α=0,\alpha = 0, 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 {u1,,um}\{u_1,\ldots,u_m\} forms a basis for C\mathcal{C} 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 2.2.

  2. 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 v1,,vrΣnv_1,\ldots,v_r\in\Sigma^n are parity check strings for the classical linear code C\mathcal{C} if

    C={uΣn:uv1==uvr=0},\mathcal{C} = \bigl\{ u\in \Sigma^n\,:\, u\cdot v_1 = \cdots = u \cdot v_r = 0 \bigr\},

    and this set of strings is minimal if removing one results in a larger code. These are called parity check strings because uu has binary dot product equal to zero with vv if and only if the bits of uu in positions where vv has 1s have even parity. So, to determine if a string uu is in the code C,\mathcal{C}, it suffices to check the parity of certain subsets of the bits of u.u.

    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 1111 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 22 — and for a single classical linear code described in the two different ways just described, it will always be the case that n=m+r.n = m + r. In particular, if we have a minimal set of mm generators, then the code encodes mm bits and we'll necessarily have 2m2^m codewords; and if we have a minimal set of rr parity check strings, then we'll have 2nr2^{n-r} 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: 111.111. We can alternatively describe the code with two parity check strings, such as 110110 and 011011 — which should look familiar from our previous discussions of this code — or we could instead take the parity check strings to be 110110 and 101,101, or 101101 and 011.011. (Generators and parity check strings are generally not unique for a given classical linear code.)

For a second example, consider the [7,4,3][7,4,3]-Hamming code. Here's one choice for a list of generators that works.

1111000011010010100101100001\begin{array}{c} 1111000\\[1mm] 0110100\\[1mm] 1010010\\[1mm] 1100001 \end{array}

And here's a choice for a list of parity checks for this code.

111100011001101010101\begin{array}{c} 1111000\\[1mm] 1100110\\[1mm] 1010101 \end{array}

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 ZZ and identity Pauli matrices. For instance, the parity check strings 110110 and 011011 for the 3-bit repetition code correspond precisely to the stabilizer generators ZZIZ\otimes Z\otimes \mathbb{I} and IZZ,\mathbb{I}\otimes Z\otimes Z, 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 ZZ 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 [7,4,3][7,4,3]-Hamming code.

111100011001101010101\begin{array}{c} 1111000\\[1mm] 1100110\\[1mm] 1010101 \end{array}

These parity check strings correspond to the following stabilizer generators (written without tensor product symbols), which we obtain by replacing each 11 by a ZZ and each 00 by an I.\mathbb{I}. These are three of the six stabilizer generators for the 7-qubit Steane code.

ZZZZIIIZZIIZZIZIZIZIZ\begin{array}{ccccccc} Z & Z & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] Z & Z & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I} \\[1mm] Z & \mathbb{I} & Z & \mathbb{I} & Z & \mathbb{I} & Z \end{array}

Let us give the name ZZ stabilizer generators to stabilizer generators like this, meaning that they only have Pauli ZZ and identity tensor factors — so XX and YY Pauli matrices never occur in ZZ stabilizer generators.

We can also consider stabilizer generators where only XX and identity Pauli matrices appear as tensor factors. Stabilizer generators like this can be viewed as being analogous to ZZ-stabilizer generators, except that they describe parity checks in the {+,}\{\vert+\rangle,\vert-\rangle\} basis rather than the standard basis. Stabilizer generators of this form are called XX stabilizer generators — so no YY or ZZ Pauli matrices are allowed this time.

For example, consider the remaining three stabilizer generators from the 7-qubit Steane code.

XXXXIIIXXIIXXIXIXIXIX\begin{array}{ccccccc} X & X & X & X & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] X & X & \mathbb{I} & \mathbb{I} & X & X & \mathbb{I} \\[1mm] X & \mathbb{I} & X & \mathbb{I} & X & \mathbb{I} & X \end{array}

They follow exactly the same pattern from the [7,4,3][7,4,3]-Hamming code as the ZZ-stabilizer generators, except this time we substitute XX for 11 rather than Z.Z. 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 [7,4,3][7,4,3]-Hamming code. (Of course, the code space for this code also includes linear combinations of these states.)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++\begin{array}{cccc} \vert {+++++++} \rangle \quad & \vert {--++++-} \rangle \quad & \vert {-+-++-+} \rangle \quad & \vert {+--++--} \rangle \\ \vert {+--+-++} \rangle \quad & \vert {-+-+-+-} \rangle \quad & \vert {--++--+} \rangle \quad & \vert {++++---} \rangle \\ \vert {----+++} \rangle \quad & \vert {++--++-} \rangle \quad & \vert {+-+-+-+} \rangle \quad & \vert {-++-+--} \rangle \\ \vert {-++--++} \rangle \quad & \vert {+-+--+-} \rangle \quad & \vert {++----+} \rangle \quad & \vert {-------} \rangle \end{array}

We can now define CSS codes in very simple terms.

Definition. A CSS code is a stabilizer code that can be expressed using only XX and ZZ stabilizer generators.

That is, CSS codes are stabilizer codes for which we have stabilizer generators in which no Pauli YY matrices appear, and for which XX and ZZ 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 XX and ZZ 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 XX or ZZ 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 ZZ stabilizer generator and an XX stabilizer generator:

ZZXX\begin{array}{cc} Z & Z \\[1mm] X & X \end{array}

It's clear that this is a CSS code, because the first stabilizer generator is a ZZ stabilizer generator and the second is an XX 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 ϕ+\vert\phi^+\rangle 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 {0,1}\{\vert 0\rangle, \vert 1\rangle\} and {+,}\{\vert +\rangle, \vert -\rangle\} bases.

ϕ+=00+112=+++2\vert\phi^+\rangle = \frac{\vert 0\rangle\vert 0\rangle + \vert 1\rangle\vert 1\rangle}{\sqrt{2}} = \frac{\vert +\rangle\vert +\rangle + \vert -\rangle\vert -\rangle}{\sqrt{2}}

The 7-qubit Steane code is another example of a CSS code.

ZZZZIIIZZIIZZIZIZIZIZXXXXIIIXXIIXXIXIXIXIX\begin{array}{ccccccc} Z & Z & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] Z & Z & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I} \\[1mm] Z & \mathbb{I} & Z & \mathbb{I} & Z & \mathbb{I} & Z \\[1mm] X & X & X & X & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] X & X & \mathbb{I} & \mathbb{I} & X & X & \mathbb{I} \\[1mm] X & \mathbb{I} & X & \mathbb{I} & X & \mathbb{I} & X \end{array}

Here we have three ZZ stabilizer generators and three XX stabilizer generators, and we've already verified that this is a valid stabilizer code.

And the 9-qubit Shor code is another example.

ZZIIIIIIIIZZIIIIIIIIIZZIIIIIIIIZZIIIIIIIIIZZIIIIIIIIZZXXXXXXIIIIIIXXXXXX\begin{array}{ccccccccc} Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I}\\[1mm] \mathbb{I} & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I}\\[1mm] \mathbb{I} & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I}\\[1mm] \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I}\\[1mm] \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I}\\[1mm] \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & \mathbb{I} & Z & Z\\[1mm] X & X & X & X & X & X & \mathbb{I} & \mathbb{I} & \mathbb{I}\\[1mm] \mathbb{I} & \mathbb{I} & \mathbb{I}& X & X & X & X & X & X \end{array}

This time we have six ZZ stabilizer generators and just two XX 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 ZZ stabilizer generator must commute with each XX stabilizer generator. So, not every collection of XX and ZZ 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 XX and ZZ errors can be detected and corrected completely independently; the ZZ stabilizer generators describe a code that protects against bit flips, and the XX stabilizer generators describe a code that independently protects against phase flips. This works because ZZ stabilizer generators necessarily commute with ZZ errors, as well as ZZ operations that are applied as corrections, so they're completely oblivious to both, and likewise for XX stabilizer generators, errors, and corrections.

As an example, let's consider the 7-qubit Steane code.

ZZZZIIIZZIIZZIZIZIZIZXXXXIIIXXIIXXIXIXIXIX\begin{array}{ccccccc} Z & Z & Z & Z & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] Z & Z & \mathbb{I} & \mathbb{I} & Z & Z & \mathbb{I} \\[1mm] Z & \mathbb{I} & Z & \mathbb{I} & Z & \mathbb{I} & Z \\[1mm] X & X & X & X & \mathbb{I} & \mathbb{I} & \mathbb{I} \\[1mm] X & X & \mathbb{I} & \mathbb{I} & X & X & \mathbb{I} \\[1mm] X & \mathbb{I} & X & \mathbb{I} & X & \mathbb{I} & X \end{array}

The basic idea for this code is now apparent: it's a [7,4,3][7,4,3]-Hamming code for bit-flip errors and a [7,4,3][7,4,3]-Hamming code for phase-flip errors. The fact that the XX and ZZ 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 ZZ stabilizer generators allow for the correction of up to jj bit-flip errors, and the XX stabilizer generators allow for the correction of up to kk phase-flip errors. For example, j=1j = 1 and k=1k = 1 for the Steane code, given that the [7,4,3][7,4,3]-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 jj and k.k. This is because, when the syndrome is measured, an arbitrary error on this number of qubits effectively collapses probabilistically into some combination of XX errors, ZZ errors, or both — and then the XX errors and ZZ 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 XX and ZZ 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 [7,4,3][7,4,3]-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 nn qubits, and let z1,,zsΣnz_1, \ldots, z_s \in \Sigma^n be the nn-bit parity check strings that correspond to the ZZ stabilizer generators of this code. This means that the classical linear code described by just the ZZ stabilizer generators, which we'll name CZ,\mathcal{C}_Z, takes the following form.

CZ={uΣn:uz1==uzs=0}\mathcal{C}_Z = \bigl\{ u \in \Sigma^n \,:\, u \cdot z_1 = \cdots = u \cdot z_s = 0 \bigr\}

In words, the classical linear code CZ\mathcal{C}_Z contains every string whose binary dot product with every one of the parity check strings z1,,zsz_1, \ldots, z_s is zero.

Along similar lines, let us take x1,,xtΣnx_1,\ldots,x_t\in\Sigma^n to be the nn-bit parity check strings corresponding to the XX stabilizer generators of our code. Thus, the classical linear code corresponding to the XX stabilizer generators takes this form.

CX={uΣn:ux1==uxt=0}\mathcal{C}_X = \bigl\{ u \in \Sigma^n \,:\, u \cdot x_1 = \cdots = u \cdot x_t = 0 \bigr\}

The XX stabilizer generators alone therefore describe a code that's similar to this code, but in the {+,}\{\vert {+}\rangle,\vert {-}\rangle\} basis rather than the standard basis.

Now we'll introduce two new classical linear codes that are derived from the same choices of strings, z1,,zsz_1,\ldots,z_s and x1,,xt,x_1,\ldots,x_t, but where we take these strings as generators rather than parity check strings. In particular, we obtain these two codes.

DZ={α1z1αszs:α1,,αs{0,1}}DX={α1x1αtxt:α1,,αt{0,1}}\begin{aligned} \mathcal{D}_Z & = \bigl\{ \alpha_1 z_1 \oplus \cdots \oplus \alpha_s z_s \,:\, \alpha_1,\ldots,\alpha_s \in \{0,1\} \bigr\}\\[1mm] \mathcal{D}_X & = \bigl\{ \alpha_1 x_1 \oplus \cdots \oplus \alpha_t x_t \,:\, \alpha_1,\ldots,\alpha_t \in \{0,1\} \bigr\} \end{aligned}

These are known as the dual codes of the codes defined previously: DZ\mathcal{D}_Z is the dual code of CZ\mathcal{C}_Z and DX\mathcal{D}_X is the dual code of CX.\mathcal{C}_X. 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 CZ\mathcal{C}_Z and CX\mathcal{C}_X 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 DZCX,\mathcal{D}_Z\subseteq\mathcal{C}_X, or equivalently, that DXCZ.\mathcal{D}_X\subseteq\mathcal{C}_Z. In words, the dual code DZ\mathcal{D}_Z includes the strings corresponding to ZZ stabilizer generators, and their containment in CX\mathcal{C}_X is equivalent to the binary dot product of each of these strings with the ones corresponding to the XX stabilizer generators being zero. That, in turn, is equivalent to each ZZ stabilizer generator commuting with each XX stabilizer generator. Alternatively, by reversing the roles of the XX and ZZ stabilizer generators and starting from the containment DXCZ,\mathcal{D}_X\subseteq\mathcal{C}_Z, 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.

uDX=12tvDXuv(for all uCZ)\vert u \oplus \mathcal{D}_X\rangle = \frac{1}{\sqrt{2^t}} \sum_{v\in\mathcal{D}_X} \vert u \oplus v\rangle \qquad \text{(for all $u\in\mathcal{C}_Z$)}

In words, these vectors are uniform superpositions over the strings in the dual code DX\mathcal{D}_X of the code corresponding to the XX stabilizer generators, shifted by (in other words, bitwise XORed with) strings in the code CZ\mathcal{C}_Z corresponding to the ZZ stabilizer generators. To be clear, different choices for the shift — represented by the string uu 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 nn-qubit standard basis state u,\vert u\rangle, for some arbitrary nn-bit string u,u, and suppose that we project this state onto the code space. That is to say, letting Π\Pi denote the projection onto the code space of our CSS code, consider the vector Πu.\Pi\vert u\rangle. There are two cases:

  • Case 1: uCZ.u\in\mathcal{C}_Z. This implies that each ZZ stabilizer generator of our CSS code acts trivially on u.\vert u\rangle. The XX stabilizer generators, on the other hand, each simply flip some of the bits of u.\vert u\rangle. In particular, for each generator vv of DX,\mathcal{D}_X, the XX stabilizer generator corresponding to vv transforms u\vert u\rangle into uv.\vert u\oplus v\rangle. By characterizing the projection Π\Pi as the average over the elements of the stabilizer (as we saw in the previous lesson), we obtain this formula:

    Πu=12tvDXuv=12tuDX.\Pi \vert u \rangle = \frac{1}{2^t} \sum_{v\in\mathcal{D}_{X}} \vert u \oplus v\rangle = \frac{1}{\sqrt{2^t}} \vert u \oplus \mathcal{D}_X\rangle.
  • Case 2: uCZ.u\notin\mathcal{C}_Z. This implies that at least one of the parity checks corresponding to the ZZ stabilizer generators fails, which is to say that u\vert u\rangle must be a 1-1 eigenvector of at least one of the ZZ stabilizer generators. The code space of the CSS code is the intersection of the +1+1 eigenspaces of the stabilizer generators. So, as a 1-1 eigenvector of at least one of the ZZ stabilizer generators, u\vert u\rangle is therefore orthogonal to the code space:

    Πu=0.\Pi\vert u\rangle = 0.

And now, as we range over all nn-bit strings u,u, discard the ones for which Πu=0,\Pi\vert u\rangle = 0, 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 XX and ZZ 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.

HnuDZ=12svDZHnuv(for uCX)H^{\otimes n} \vert u \oplus \mathcal{D}_Z\rangle = \frac{1}{\sqrt{2^s}} \sum_{v\in\mathcal{D}_Z} H^{\otimes n}\vert u \oplus v\rangle \qquad \text{(for $u\in\mathcal{C}_X$)}

In essence, XX and ZZ have been swapped in each instance in which they appear — but we must also swap the standard basis for the {+,}\{\vert+\rangle,\vert-\rangle\} 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 XX and ZZ stabilizer generators are the same: 1111000,1111000, 1100110,1100110, and 1010101.1010101. The codes CX\mathcal{C}_X and CZ\mathcal{C}_Z are therefore the same; both are equal to the [7,4,3][7,4,3]-Hamming code.

CX=CZ={0000000,0000111,0011001,0011110,0101010,0101101,0110011,0110100,1001011,1001100,1010010,1010101,1100001,1100110,1111000,1111111}\mathcal{C}_X = \mathcal{C}_Z = \{0000000, 0000111, 0011001, 0011110, 0101010, 0101101, 0110011, 0110100, 1001011, 1001100, 1010010, 1010101, 1100001, 1100110, 1111000, 1111111\}

The dual codes DX\mathcal{D}_X and DZ\mathcal{D}_Z are therefore also the same. We have three generators, so we obtain eight strings.

DX=DZ={0000000,0011110,0101101,0110011,1001011,1010101,1100110,1111000}\mathcal{D}_X = \mathcal{D}_Z = \{0000000, 0011110, 0101101, 0110011, 1001011, 1010101, 1100110, 1111000\}

These strings are all contained in the [7,4,3][7,4,3]-Hamming code, and so the CSS condition is satisfied: DZCX,\mathcal{D}_Z \subseteq \mathcal{C}_X, or equivalently, DXCZ.\mathcal{D}_X \subseteq \mathcal{C}_Z.

Given that DX\mathcal{D}_X contains half of all of the strings in CZ,\mathcal{C}_Z, there are only two different vectors uDX\vert u\oplus \mathcal{D}_X\rangle that can be obtained by choosing uCZ.u\in\mathcal{C}_Z. 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 0\vert 0\rangle and 1\vert 1\rangle as follows.

00000000+0011110+0101101+0110011+1001011+1010101+1100110+1111000810000111+0011001+0101010+0110100+1001100+1010010+1100001+11111118\begin{aligned} \vert 0\rangle & \mapsto \frac{ \vert 0000000\rangle + \vert 0011110\rangle + \vert 0101101\rangle + \vert 0110011\rangle + \vert 1001011\rangle + \vert 1010101\rangle + \vert 1100110\rangle + \vert 1111000\rangle }{\sqrt{8}}\\[4mm] \vert 1\rangle & \mapsto \frac{ \vert 0000111\rangle + \vert 0011001\rangle + \vert 0101010\rangle + \vert 0110100\rangle + \vert 1001100\rangle + \vert 1010010\rangle + \vert 1100001\rangle + \vert 1111111\rangle }{\sqrt{8}} \end{aligned}

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.

Was this page helpful?
Report a bug or request content on GitHub.