Saltar al contenido principal

Códigos CSS

Códigos lineales clásicos

Los códigos correctores de errores clásicos se estudiaron por primera vez en la década de 1940, y desde entonces se conocen muchos códigos diferentes. Los códigos más estudiados y utilizados pertenecen a la categoría de los llamados códigos lineales. Lo que significa exactamente la palabra "lineal" en este contexto quedará claro enseguida. En términos simples, los códigos lineales son códigos estabilizadores, pero de naturaleza clásica. Los códigos CSS son esencialmente pares de códigos lineales clásicos que se combinan para formar un código corrector de errores cuánticos. Para comprender la siguiente discusión, necesitamos conocer algunas propiedades básicas de los códigos lineales clásicos.

Sea Σ\Sigma el alfabeto binario para toda esta discusión. Cuando hablamos de un código lineal clásico, nos referimos a un conjunto no vacío CΣn\mathcal{C}\subseteq\Sigma^n de cadenas binarias de longitud nn (para un entero positivo nn) que debe satisfacer exactamente una propiedad fundamental: si uu y vv son cadenas binarias en C\mathcal{C}, entonces uvu\oplus v también debe estar en C\mathcal{C}. Aquí, uvu\oplus v denota el OR exclusivo bit a bit de uu y vv, como lo hemos encontrado varias veces en el curso "Fundamentos de los algoritmos cuánticos".

En esencia, en los códigos lineales clásicos consideramos las cadenas binarias de longitud nn como vectores nn-dimensionales con entradas de {0,1}\{0, 1\} y requerimos que el código mismo forme un subespacio lineal. En lugar de la suma vectorial ordinaria sobre los números reales o complejos, usamos la suma módulo 22, es decir, el OR exclusivo. Es decir: si uu y vv son dos palabras código en C\mathcal{C}, entonces u+vu + v módulo 2, es decir, uvu\oplus v, también debe ser una palabra código en C\mathcal{C}. Nótese en particular que esto también es cierto cuando u=vu = v. De esto se deduce que C\mathcal{C} debe contener la cadena nula 0n0^n, ya que el OR exclusivo bit a bit de cualquier cadena consigo misma es la cadena nula.

Ejemplo: el código de repetición de 3 bits

El código de repetición de 3 bits es un ejemplo de un código lineal clásico. Concretamente, C={000,111}\mathcal{C} = \{000,111\}, y para la condición de linealidad hay exactamente dos opciones para uu y dos para vv. Es fácil verificar que para los cuatro pares posibles, el OR exclusivo bit a bit siempre da una palabra código:

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.

Ejemplo: el código de Hamming [7,4,3][7,4,3]

Aquí hay otro ejemplo de un código lineal clásico: el código de Hamming [7,4,3][7,4,3]. Fue uno de los primeros códigos correctores de errores clásicos jamás descubiertos y consta de estas 16 cadenas binarias de longitud 7. (A veces se entiende por código de Hamming [7,4,3][7,4,3] el código con las cadenas invertidas, pero aquí consideramos el código con las cadenas que se muestran a continuación.)

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}

Hay una lógica simple detrás de la selección de estas cadenas, pero es secundaria para esta lección y no se explica aquí. Basta con señalar que este es un código lineal clásico: el XOR de cualesquiera dos de estas cadenas siempre da otra cadena en el código.

La notación [7,4,3][7,4,3] (entre corchetes simples) tiene un significado similar a la notación de doble corchete para códigos estabilizadores de la lección anterior, pero aplicada a códigos lineales clásicos. Concretamente significa: las palabras código tienen 77 bits, se pueden codificar 44 bits (ya que hay 16=2416 = 2^4 palabras código), y se trata de un código con distancia 33, es decir, dos palabras código diferentes difieren en al menos 33 posiciones — por lo que se necesitan invertir al menos 33 bits para transformar una palabra código en otra. El hecho de que sea un código con distancia 33 implica que puede corregir hasta un error de inversión de bit.

Descripción de códigos lineales clásicos

Los ejemplos mencionados son códigos lineales clásicos muy simples, pero incluso en el código de Hamming [7,4,3][7,4,3], la mera enumeración de las palabras código resulta algo enigmática. Hay formas mejores y más eficientes de describir códigos lineales clásicos, entre ellas las dos siguientes.

  1. Generadores. Una forma de describir un código lineal clásico es una lista mínima de palabras código que generan el código, es decir, seleccionando todos los subconjuntos posibles de estas palabras código y aplicando XOR se obtiene el código completo.

    Más precisamente, las cadenas u1,,umΣnu_1,\ldots,u_m\in\Sigma^n generan el código lineal clásico C\mathcal{C} si

    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\},

    donde αu=u\alpha u = u para α=1\alpha = 1 y αu=0n\alpha u = 0^n para α=0\alpha = 0, y esta lista se denomina mínima si la eliminación de cualquiera de las cadenas genera un código más pequeño. Una forma natural de ver esta descripción es que {u1,,um}\{u_1,\ldots,u_m\} forma una base para C\mathcal{C} como subespacio — consideramos las cadenas como vectores con entradas binarias y trabajamos en un espacio vectorial donde la aritmética se realiza módulo 22.

  2. Verificaciones de paridad. Otra descripción natural de un código lineal clásico son las verificaciones de paridad — es decir, una lista mínima de cadenas binarias tales que exactamente las cadenas del código son aquellas cuyo producto escalar binario con cada una de estas cadenas de verificación de paridad es cero. (Al igual que el OR exclusivo bit a bit, el producto escalar binario ha aparecido varias veces en el curso "Fundamentos de los algoritmos cuánticos".)

    Es decir: las cadenas v1,,vrΣnv_1,\ldots,v_r\in\Sigma^n son cadenas de verificación de paridad para el código lineal clásico C\mathcal{C} si

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

    y este conjunto de cadenas es mínimo si la eliminación de cualquiera de ellas conduce a un código más grande. Se llaman cadenas de verificación de paridad porque uu tiene producto escalar binario cero con vv exactamente cuando los bits de uu en las posiciones donde vv tiene un 1 tienen paridad par. Para verificar si una cadena uu está en el código C\mathcal{C}, basta entonces con comprobar la paridad de ciertos subconjuntos de los bits de uu.

    Una nota importante: el producto escalar binario no es un producto interno en el sentido formal. En particular, que el producto escalar binario de dos cadenas sea cero no significa que sean ortogonales en el sentido habitual. Por ejemplo, el producto escalar binario de la cadena 1111 consigo misma es cero — una cadena de verificación de paridad de un código lineal clásico puede pertenecer al propio código.

Los códigos lineales clásicos sobre el alfabeto binario siempre contienen una cantidad de cadenas que es una potencia de 22 — y para un código lineal clásico representado de ambas formas descritas, siempre se cumple n=m+rn = m + r. Concretamente: si tenemos un conjunto mínimo de mm generadores, el código codifica mm bits y tiene exactamente 2m2^m palabras código; si tenemos un conjunto mínimo de rr cadenas de verificación de paridad, hay 2nr2^{n-r} palabras código. Cada generador duplica el tamaño del espacio de código, mientras que cada cadena de verificación de paridad lo divide a la mitad.

Por ejemplo, el código de repetición de 3 bits es un código lineal que puede describirse de ambas formas. Hay exactamente un generador que funciona: 111111. Alternativamente, el código puede describirse mediante dos cadenas de verificación de paridad, por ejemplo 110110 y 011011 — que deberían resultar familiares de discusiones anteriores de este código — o también 110110 y 101101 o 101101 y 011011. (Los generadores y las cadenas de verificación de paridad no son, en general, únicos para un código lineal clásico dado.)

Como segundo ejemplo, consideremos el código de Hamming [7,4,3][7,4,3]. Aquí hay una posible lista de generadores:

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

Y aquí hay una posible lista de verificaciones de paridad para este código:

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

Aquí vemos, por cierto, que todas las cadenas de verificación de paridad pertenecen al propio código.

Una observación final sobre los códigos lineales clásicos que los conecta con el formalismo de estabilizadores: las cadenas de verificación de paridad corresponden a generadores de estabilizador que contienen solo matrices de Pauli ZZ e identidad. Las cadenas de verificación de paridad 110110 y 011011 del código de repetición de 3 bits, por ejemplo, corresponden exactamente a los generadores de estabilizador ZZIZ\otimes Z\otimes \mathbb{I} y IZZ\mathbb{I}\otimes Z\otimes Z, lo cual es consistente con las discusiones sobre observables de Pauli de la lección anterior.

Definición de los códigos CSS

Los códigos CSS son códigos estabilizadores que se obtienen combinando ciertos pares de códigos lineales clásicos. Esto no funciona para cualesquiera dos códigos lineales clásicos — los dos códigos deben tener una relación particular entre sí. Sin embargo, esta construcción abre muchas posibilidades para códigos correctores de errores cuánticos, que se basan en parte en más de 75 años de teoría de codificación clásica.

En el formalismo de estabilizadores, los generadores de estabilizador que contienen solo matrices de Pauli ZZ e identidad son equivalentes a verificaciones de paridad, como acabamos de ver con el código de repetición de 3 bits. Como otro ejemplo, consideremos las siguientes cadenas de verificación de paridad para el código de Hamming [7,4,3][7,4,3]:

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

Estas cadenas de verificación de paridad corresponden a los siguientes generadores de estabilizador (sin símbolos de producto tensorial), que se obtienen reemplazando cada 11 por ZZ y cada 00 por I\mathbb{I}. Estos son tres de los seis generadores de estabilizador del código de Steane de 7 qubits.

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}

Los generadores de estabilizador de este tipo — en los que solo aparecen factores tensoriales de Pauli ZZ e identidad (no aparecen matrices de Pauli XX ni YY) — los llamamos generadores de estabilizador ZZ.

Además, existen generadores de estabilizador en los que solo aparecen matrices de Pauli XX e identidad como factores tensoriales. Tales generadores son análogos a los generadores de estabilizador ZZ, pero describen verificaciones de paridad en la base {+,}\{\vert+\rangle,\vert-\rangle\} en lugar de la base estándar. Los generadores de esta forma se llaman generadores de estabilizador XX — aquí no se permiten matrices de Pauli YY ni ZZ.

Como ejemplo, consideremos los tres generadores de estabilizador restantes del código de Steane de 7 qubits:

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}

Siguen exactamente el mismo patrón del código de Hamming [7,4,3][7,4,3] que los generadores de estabilizador ZZ, pero esta vez se usa XX en lugar de ZZ para cada 11. Solo con estos tres generadores de estabilizador se obtiene un código que contiene los 16 estados que se muestran aquí — se obtienen aplicando operaciones de Hadamard a los estados de la base estándar correspondientes a las cadenas del código de Hamming [7,4,3][7,4,3]. (Por supuesto, el espacio de código también contiene combinaciones lineales de estos estados.)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++\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}

Los códigos CSS pueden definirse ahora en términos muy simples.

Definición

Un código CSS es un código estabilizador que puede expresarse exclusivamente con generadores de estabilizador XX y ZZ.

Es decir, los códigos CSS son códigos estabilizadores para los cuales existen generadores de estabilizador en los que no aparecen matrices de Pauli YY y en los que XX y ZZ nunca ocurren en el mismo generador de estabilizador.

Para ser claros: según esta definición, un código CSS es aquel en el que es posible elegir exclusivamente generadores de estabilizador XX y ZZ — pero debemos tener en cuenta que en los códigos estabilizadores hay libertad en la elección de los generadores. Por lo tanto, en general habrá diferentes elecciones de generadores de estabilizador para un código CSS que no son generadores de estabilizador XX o ZZ (además de al menos una elección en la que sí lo son).

Aquí hay un ejemplo muy simple de un código CSS que contiene tanto un generador de estabilizador ZZ como un generador de estabilizador XX:

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

Es obvio que este es un código CSS: el primer generador de estabilizador es un generador de estabilizador ZZ y el segundo es un generador de estabilizador XX. Por supuesto, un código CSS también debe ser un código estabilizador válido — es decir, los generadores de estabilizador deben conmutar, formar un conjunto generador mínimo y fijar al menos un vector de estado cuántico. Estos requisitos son fáciles de verificar para este código. Como se menciónó en la lección anterior, el espacio de código de este código es el espacio unidimensional generado por el estado de Bell ϕ+\vert\phi^+\rangle. Que ambos generadores de estabilizador fijan este estado se deduce de las dos expresiones siguientes para un e-bit y de una interpretación de estos generadores de estabilizador como verificaciones de paridad en la base {0,1}\{\vert 0\rangle, \vert 1\rangle\} y en la base {+,}\{\vert +\rangle, \vert -\rangle\}.

ϕ+=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}}

El código de Steane de 7 qubits es otro ejemplo de un código CSS.

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}

Aquí tenemos tres generadores de estabilizador ZZ y tres generadores de estabilizador XX, y ya hemos verificado que se trata de un código estabilizador válido.

Y el código de Shor de 9 qubits es otro ejemplo:

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}

Esta vez tenemos seis generadores de estabilizador ZZ y solo dos generadores de estabilizador XX. Esto está bien — no tiene por qué haber equilibrio o simetría entre los dos tipos de generadores (aunque frecuentemente la hay).

Una vez más, los códigos CSS deben ser códigos estabilizadores válidos; en particular, cada generador de estabilizador ZZ debe conmutar con cada generador de estabilizador XX. No toda combinación de generadores de estabilizador XX y ZZ define, por tanto, un código CSS válido.

Detección y corrección de errores

En cuanto a la detección y corrección de errores, los códigos CSS tienen, en general, una propiedad similar a la del código de Shor de 9 qubits: los errores XX y ZZ pueden detectarse y corregirse de forma completamente independiente. Los generadores de estabilizador ZZ describen un código que protege contra inversiones de bit, y los generadores de estabilizador XX describen un código que protege independientemente contra inversiones de fase. Esto funciona porque los generadores de estabilizador ZZ necesariamente conmutan con los errores ZZ y las correcciones ZZ — son por tanto completamente invisibles para ambos — y lo mismo ocurre recíprocamente con los generadores de estabilizador XX, errores y correcciones.

Como ejemplo, consideremos el código de Steane de 7 qubits:

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}

La idea básica de este código es ahora clara: es un código de Hamming [7,4,3][7,4,3] para errores de inversión de bit y un código de Hamming [7,4,3][7,4,3] para errores de inversión de fase. Que los generadores de estabilizador XX y ZZ conmuten es, en cierto modo, una circunstancia afortunada — si no fuera así, no sería un código estabilizador válido. De hecho, sin embargo, hay muchos ejemplos conocidos de códigos lineales clásicos que conducen a un código estabilizador válido de manera similar.

Supongamos que tenemos un código CSS en el que los generadores de estabilizador ZZ permiten la corrección de hasta jj errores de inversión de bit y los generadores de estabilizador XX permiten la corrección de hasta kk errores de inversión de fase. Para el código de Steane, por ejemplo, j=1j = 1 y k=1k = 1, ya que el código de Hamming [7,4,3][7,4,3] puede corregir una inversión de bit. Por la discretización de errores, se deduce que este código CSS puede corregir errores arbitrarios en un número de qubits hasta el mínimo de jj y kk. Pues al medir el síndrome, un error arbitrario en ese número de qubits colapsa probabilísticamente en una combinación de errores XX, errores ZZ o ambos — y luego los errores XX y los errores ZZ se detectan y corrigen de forma independiente.

En resumen: si tenemos dos códigos lineales clásicos (o dos copias de un solo código lineal clásico) que son compatibles — es decir, definen generadores de estabilizador XX y ZZ que conmutan — entonces el código CSS que obtenemos al combinarlos hereda las propiedades de corrección de errores de esos dos códigos en el sentido descrito.

Sin embargo, hay un precio que pagar: no podemos codificar tantos qubits como bits en los dos códigos clásicos. Esto se debe a que el número total de generadores de estabilizador del código CSS es la suma de las verificaciones de paridad de los dos códigos lineales clásicos, y cada generador de estabilizador reduce a la mitad la dimensión del espacio de código. Por ejemplo, el código de Hamming [7,4,3][7,4,3] permite la codificación de cuatro bits clásicos (ya que solo tiene tres cadenas de verificación de paridad), mientras que el código de Steane de 7 qubits codifica solo un qubit (ya que tiene seis generadores de estabilizador).

Espacios de código de los códigos CSS

Para concluir nuestra discusión sobre los códigos CSS, consideremos los espacios de código de estos códigos. Esto nos da la oportunidad de examinar más de cerca la relación que debe existir entre dos códigos lineales clásicos para que sean compatibles y puedan combinarse en un código CSS.

Consideremos un código CSS arbitrario sobre nn qubits y sea z1,,zsΣnz_1, \ldots, z_s \in \Sigma^n el conjunto de las cadenas de verificación de paridad de nn bits correspondientes a los generadores de estabilizador ZZ de este código. El código lineal clásico descrito solo por los generadores de estabilizador ZZ, al que llamamos CZ\mathcal{C}_Z, tiene entonces la siguiente forma:

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\}

En otras palabras, el código lineal clásico CZ\mathcal{C}_Z contiene exactamente las cadenas cuyo producto escalar binario con cada una de las cadenas de verificación de paridad z1,,zsz_1, \ldots, z_s es cero.

Correspondientemente, sea x1,,xtΣnx_1,\ldots,x_t\in\Sigma^n el conjunto de las cadenas de verificación de paridad de nn bits correspondientes a los generadores de estabilizador XX de nuestro código. El código lineal clásico de los generadores de estabilizador XX tiene entonces esta forma:

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\}

Los generadores de estabilizador XX solos describen, por tanto, un código similar a este, pero en la base {+,}\{\vert {+}\rangle,\vert {-}\rangle\} en lugar de la base estándar.

Ahora introducimos dos nuevos códigos lineales clásicos que se derivan de las mismas cadenas z1,,zsz_1,\ldots,z_s y x1,,xtx_1,\ldots,x_t, pero esta vez usadas como generadores en lugar de cadenas de verificación de paridad. Obtenemos los siguientes dos códigos:

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}

Estos se denominan códigos duales de los códigos definidos anteriormente: DZ\mathcal{D}_Z es el código dual de CZ\mathcal{C}_Z y DX\mathcal{D}_X es el código dual de CX\mathcal{C}_X. Puede que no sea obvio por el momento por qué estos códigos duales son relevantes, pero desempeñan un papel importante por varias razones, incluyendo las dos explicadas en los párrafos siguientes.

En primer lugar, las condiciones que dos códigos lineales clásicos CZ\mathcal{C}_Z y CX\mathcal{C}_X deben satisfacer para ser compatibles (es decir, poder combinarse en un código CSS) pueden describirse de forma simple usando los códigos duales. Concretamente, debe cumplirse: DZCX\mathcal{D}_Z\subseteq\mathcal{C}_X, lo cual es equivalente a DXCZ\mathcal{D}_X\subseteq\mathcal{C}_Z. En otras palabras: el código dual DZ\mathcal{D}_Z contiene las cadenas de los generadores de estabilizador ZZ, y su inclusión en CX\mathcal{C}_X es equivalente a que el producto escalar binario de cada una de estas cadenas con las de los generadores de estabilizador XX sea cero. Esto, a su vez, es equivalente a que cada generador de estabilizador ZZ conmute con cada generador de estabilizador XX. Alternativamente, se puede llegar a la misma conclusión intercambiando los roles de los generadores de estabilizador XX y ZZ y partiendo de la inclusión DXCZ\mathcal{D}_X\subseteq\mathcal{C}_Z.

En segundo lugar, usando los códigos duales se pueden describir fácilmente los espacios de código de un código CSS dado. En particular, el espacio de código está generado por vectores de la siguiente forma:

uDX=12tvDXuv(para todo 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{(para todo $u\in\mathcal{C}_Z$)}

En otras palabras, estos vectores son superposiciones equiponderadas sobre las cadenas del código dual DX\mathcal{D}_X del código correspondiente a los generadores de estabilizador XX, desplazadas (es decir, XOR bit a bit) con cadenas del código CZ\mathcal{C}_Z de los generadores de estabilizador ZZ. Para aclarar: diferentes elecciones del desplazamiento — representado por la cadena uu en esta expresión — pueden conducir al mismo vector. Estos estados no son, por tanto, todos distintos, pero juntos generan todo el espacio de código.

Aquí hay una explicación intuitiva de por qué tales vectores están en el espacio de código y lo generan. Consideremos el estado de la base estándar de nn qubits u\vert u\rangle para una cadena de nn bits arbitraria uu y proyectemos este estado sobre el espacio de código. Sea Π\Pi la proyección sobre el espacio de código de nuestro código CSS y consideremos el vector Πu\Pi\vert u\rangle. Hay dos casos:

  • Caso 1: uCZ.u\in\mathcal{C}_Z. Esto significa que cada generador de estabilizador ZZ de nuestro código CSS actúa trivialmente sobre u\vert u\rangle. Los generadores de estabilizador XX, en cambio, invierten ciertos bits de u\vert u\rangle. En particular, para cada generador vv de DX\mathcal{D}_X, el generador de estabilizador XX correspondiente transforma u\vert u\rangle en uv\vert u\oplus v\rangle. Caracterizando la proyección Π\Pi como el promedio sobre los elementos del estabilizador (como se vio en la lección anterior), obtenemos la siguiente fórmula:

    Π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.
  • Caso 2: uCZ.u\notin\mathcal{C}_Z. Esto significa que al menos una de las verificaciones de paridad correspondientes a los generadores de estabilizador ZZ falla, es decir, u\vert u\rangle es un vector propio con valor propio 1-1 de al menos un generador de estabilizador ZZ. El espacio de código del código CSS es la intersección de los espacios propios de valor propio +1+1 de los generadores de estabilizador. Como vector propio de valor propio 1-1 de al menos un generador de estabilizador ZZ, u\vert u\rangle es por tanto ortogonal al espacio de código:

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

Si ahora recorremos todas las cadenas de nn bits uu, descartamos los casos con Πu=0\Pi\vert u\rangle = 0 y normalizamos los restantes, obtenemos los vectores descritos anteriormente — lo que demuestra que generan el espacio de código.

Usando la simetría entre los generadores de estabilizador XX y ZZ, el espacio de código también puede describirse de una forma similar pero diferente. Está generado por vectores de la siguiente forma:

HnuDZ=12svDZHnuv(para 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{(para $u\in\mathcal{C}_X$)}

En esencia, se han intercambiado XX y ZZ en cada aparición — pero también debemos intercambiar la base estándar por la base {+,}\{\vert+\rangle,\vert-\rangle\}, razón por la cual aparecen las operaciones de Hadamard.

Como ejemplo, consideremos el código de Steane de 7 qubits. Las cadenas de verificación de paridad para los generadores de estabilizador XX y ZZ son las mismas: 11110001111000, 11001101100110 y 10101011010101. Los códigos CX\mathcal{C}_X y CZ\mathcal{C}_Z son por tanto iguales; ambos son el código de Hamming [7,4,3][7,4,3].

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\}

Los códigos duales DX\mathcal{D}_X y DZ\mathcal{D}_Z también son por tanto iguales. Tenemos tres generadores y obtenemos ocho cadenas:

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

Todas estas cadenas están contenidas en el código de Hamming [7,4,3][7,4,3], por lo que se satisface la condición CSS: DZCX\mathcal{D}_Z \subseteq \mathcal{C}_X o, equivalentemente, DXCZ\mathcal{D}_X \subseteq \mathcal{C}_Z.

Dado que DX\mathcal{D}_X contiene la mitad de todas las cadenas en CZ\mathcal{C}_Z, solo hay dos vectores distintos uDX\vert u\oplus \mathcal{D}_X\rangle que surgen al elegir uCZu\in\mathcal{C}_Z. Esto es de esperar, ya que el código de Steane de 7 qubits tiene un espacio de código bidimensional. Podemos usar los dos estados así obtenidos para codificar los estados lógicos 0\vert 0\rangle y 1\vert 1\rangle de la siguiente manera:

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}

Como de costumbre, esta elección no es obligatoria — podemos usar el espacio de código a voluntad para codificar qubits. Sin embargo, esta codificación es consistente con el ejemplo de un circuito de codificación para el código de Steane de 7 qubits de la lección anterior.