Pular para o conteúdo principal

Códigos CSS

Códigos lineares clássicos

Os códigos de correção de erros clássicos foram estudados pela primeira vez na década de 1940, e hoje se conhecem muitos códigos diferentes. Os mais amplamente estudados e utilizados pertencem a uma categoria conhecida como códigos lineares. Vamos entender em breve o que a palavra "linear" significa nesse contexto, mas uma forma muito simples de descrever os códigos lineares é que eles são códigos estabilizadores que, por acaso, são clássicos. Os códigos CSS são, essencialmente, pares de códigos lineares clássicos combinados para criar um código de correção de erros quânticos. Portanto, para a discussão a seguir, precisamos entender alguns conceitos básicos sobre códigos lineares clássicos.

Seja Σ\Sigma o alfabeto binário para toda esta discussão. Quando nos referimos a um código linear clássico, queremos dizer um conjunto não vazio CΣn\mathcal{C}\subseteq\Sigma^n de strings binárias de comprimento n,n, para algum inteiro positivo n,n, que deve satisfazer apenas uma propriedade básica: se uu e vv são strings binárias em C,\mathcal{C}, então a string uvu\oplus v também está em C.\mathcal{C}. Aqui, uvu\oplus v denota o OU exclusivo bit a bit de uu e v,v, como vimos várias vezes no curso "Fundamentos de algoritmos quânticos".

Em essência, quando nos referimos a um código de correção de erros clássico como linear, estamos pensando em strings binárias de comprimento nn como vetores de nn dimensões, onde as entradas são 00 ou 1,1, e exigindo que o próprio código forme um subespaço linear. Em vez da adição vetorial ordinária sobre os reais ou os complexos, utilizamos a adição módulo 2,2, que é simplesmente o OU exclusivo. Ou seja, se temos duas palavras-código uu e v,v, significando que uu e vv são strings binárias em C,\mathcal{C}, então u+vu + v módulo 2, isto é, uv,u\oplus v, também deve ser uma palavra-código em C.\mathcal{C}. Note, em particular, que essa implicação deve ser verdadeira mesmo quando u=v.u = v. Isso implica que C\mathcal{C} deve incluir a string de zeros 0n,0^n, pois o OU exclusivo bit a bit de qualquer string consigo mesma é a string de zeros.

Exemplo: o código de repetição de 3 bits

O código de repetição de 3 bits é um exemplo de código linear clássico. Em particular, temos C={000,111},\mathcal{C} = \{000,111\}, portanto, com relação à condição de linearidade, há apenas duas escolhas possíveis para uu e duas para v.v. É simples verificar os quatro pares possíveis e confirmar que sempre obtemos uma palavra-código ao calcular o OU exclusivo bit a bit:

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.

Exemplo: o código de Hamming [7,4,3][7,4,3]

Aqui está outro exemplo de código linear clássico chamado código de Hamming [7,4,3][7,4,3]. Foi um dos primeiros códigos de correção de erros clássicos já descobertos, e consiste nestas 16 strings binárias de comprimento 7. (Às vezes, o código de Hamming [7,4,3][7,4,3] é entendido como o código com essas strings invertidas, mas vamos considerá-lo como o código contendo as strings mostradas aqui.)

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}

Há uma lógica muito simples por trás da seleção dessas strings, mas ela é secundária ao conteúdo da lição e não será explicada aqui. Por enquanto, basta observar que este é um código linear clássico: calcular o XOR de quaisquer duas dessas strings sempre resultará em outra string do código.

A notação [7,4,3][7,4,3] (entre colchetes simples) tem um significado análogo à notação de colchetes duplos para códigos estabilizadores mencionada na lição anterior, mas aqui se aplica a códigos lineares clássicos. Em particular, as palavras-código têm 77 bits, podemos codificar 44 bits usando o código (pois há 16=2416 = 2^4 palavras-código), e esse é um código de distância 33, o que significa que quaisquer duas palavras-código distintas diferem em pelo menos 33 posições — ou seja, pelo menos 33 bits precisam ser invertidos para transformar uma palavra-código em outra. O fato de ser um código de distância 33 implica que ele pode corrigir até um erro de inversão de bit.

Descrevendo códigos lineares clássicos

Os exemplos mencionados são exemplos muito simples de códigos lineares clássicos, mas mesmo o código de Hamming [7,4,3][7,4,3] parece um pouco misterioso quando as palavras-código são simplesmente listadas. Existem formas melhores e mais eficientes de descrever códigos lineares clássicos, incluindo as duas a seguir.

  1. Geradores. Uma forma de descrever um código linear clássico é com uma lista mínima de palavras-código que geram o código, significando que, ao considerar todos os subconjuntos possíveis dessas palavras-código e calcular seus XORs, obtemos o código inteiro.

    Em maior detalhe, as strings u1,,umΣnu_1,\ldots,u_m\in\Sigma^n geram o código linear clássico C\mathcal{C} se

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

    com o entendimento de que αu=u\alpha u = u quando α=1\alpha = 1 e αu=0n\alpha u = 0^n quando α=0,\alpha = 0, e dizemos que essa lista é mínima se a remoção de uma das strings gera um código menor. Uma forma natural de pensar nessa descrição é que a coleção {u1,,um}\{u_1,\ldots,u_m\} forma uma base para C\mathcal{C} como subespaço, onde pensamos nas strings como vetores com entradas binárias, lembrando que estamos trabalhando em um espaço vetorial onde a aritmética é feita módulo 2.2.

  2. Verificações de paridade. Outra forma natural de descrever um código linear clássico é por meio de verificações de paridade — ou seja, uma lista mínima de strings binárias tais que as strings no código são precisamente aquelas cujo produto escalar binário com cada uma dessas strings de verificação de paridade é zero. (Similar ao OU exclusivo bit a bit, o produto escalar binário apareceu várias vezes em "Fundamentos de algoritmos quânticos".)

    Ou seja, as strings v1,,vrΣnv_1,\ldots,v_r\in\Sigma^n são strings de verificação de paridade para o código linear clássico C\mathcal{C} se

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

    e esse conjunto de strings é mínimo se a remoção de uma resulta em um código maior. Essas são chamadas de strings de verificação de paridade porque uu tem produto escalar binário igual a zero com vv se e somente se os bits de uu nas posições onde vv tem 1s têm paridade par. Portanto, para determinar se uma string uu está no código C,\mathcal{C}, basta verificar a paridade de certos subconjuntos dos bits de u.u.

    Uma coisa importante a observar é que o produto escalar binário não é um produto interno no sentido formal. Em particular, quando duas strings têm produto escalar binário igual a zero, isso não significa que elas são ortogonais da forma que normalmente pensamos em ortogonalidade. Por exemplo, o produto escalar binário da string 1111 consigo mesma é zero — portanto, é possível que uma string de verificação de paridade de um código linear clássico esteja ela própria no código.

Os códigos lineares clássicos sobre o alfabeto binário sempre incluem um número de strings que é uma potência de 22 — e para um único código linear clássico descrito das duas formas acima, sempre teremos n=m+r.n = m + r. Em particular, se temos um conjunto mínimo de mm geradores, então o código codifica mm bits e necessariamente teremos 2m2^m palavras-código; e se temos um conjunto mínimo de rr strings de verificação de paridade, então teremos 2nr2^{n-r} palavras-código. Portanto, cada gerador dobra o tamanho do espaço do código enquanto cada string de verificação de paridade reduz o tamanho à metade.

Por exemplo, o código de repetição de 3 bits é um código linear, portanto pode ser descrito de ambas as formas. Em particular, há apenas uma escolha de gerador que funciona: 111.111. Como alternativa, podemos descrever o código com duas strings de verificação de paridade, como 110110 e 011011 — que devem parecer familiares das nossas discussões anteriores sobre esse código — ou poderíamos escolher as strings de verificação de paridade 110110 e 101,101, ou 101101 e 011.011. (Geradores e strings de verificação de paridade geralmente não são únicos para um dado código linear clássico.)

Para um segundo exemplo, considere o código de Hamming [7,4,3][7,4,3]. Aqui está uma escolha de lista de geradores que funciona.

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

E aqui está uma escolha de lista de verificações de paridade para esse código.

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

Aqui, aliás, observamos que todas as nossas strings de verificação de paridade estão elas próprias no código.

Uma observação final sobre os códigos lineares clássicos, que os conecta ao formalismo estabilizador, é que as strings de verificação de paridade são equivalentes a geradores estabilizadores compostos apenas por matrizes de Pauli ZZ e identidade. Por exemplo, as strings de verificação de paridade 110110 e 011011 para o código de repetição de 3 bits correspondem precisamente aos geradores estabilizadores ZZIZ\otimes Z\otimes \mathbb{I} e IZZ,\mathbb{I}\otimes Z\otimes Z, o que é consistente com as discussões sobre observáveis de Pauli da lição anterior.

Definição de códigos CSS

Os códigos CSS são códigos estabilizadores obtidos pela combinação de certos pares de códigos lineares clássicos. Isso não funciona para dois códigos lineares clássicos arbitrários — os dois códigos devem ter uma certa relação. Ainda assim, essa construção abre muitas possibilidades para códigos de correção de erros quânticos, com base em mais de 75 anos de teoria de codificação clássica.

No formalismo estabilizador, os geradores estabilizadores contendo apenas matrizes de Pauli ZZ e identidade são equivalentes a verificações de paridade, como acabamos de observar para o código de repetição de 3 bits. Para outro exemplo, considere as seguintes strings de verificação de paridade para o código de Hamming [7,4,3][7,4,3].

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

Essas strings de verificação de paridade correspondem aos seguintes geradores estabilizadores (escritos sem símbolos de produto tensorial), que obtemos substituindo cada 11 por um ZZ e cada 00 por um I.\mathbb{I}. Esses são três dos seis geradores estabilizadores para o 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}

Vamos dar o nome de geradores estabilizadores ZZ a geradores estabilizadores como esse, ou seja, aqueles que possuem apenas fatores tensoriais Pauli ZZ e identidade — portanto, as matrizes de Pauli XX e YY nunca ocorrem em geradores estabilizadores ZZ.

Também podemos considerar geradores estabilizadores nos quais apenas matrizes de Pauli XX e identidade aparecem como fatores tensoriais. Geradores estabilizadores como esse podem ser vistos como análogos aos geradores estabilizadores ZZ, exceto que descrevem verificações de paridade na base {+,}\{\vert+\rangle,\vert-\rangle\} em vez da base padrão. Geradores estabilizadores dessa forma são chamados de geradores estabilizadores XX — portanto, matrizes de Pauli YY ou ZZ não são permitidas desta vez.

Por exemplo, considere os três geradores estabilizadores restantes do 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}

Eles seguem exatamente o mesmo padrão do código de Hamming [7,4,3][7,4,3] que os geradores estabilizadores ZZ, exceto que desta vez substituímos XX por 11 em vez de Z.Z. O que obtemos apenas com esses três geradores estabilizadores é um código que inclui os 16 estados mostrados aqui, que obtemos aplicando operações de Hadamard aos estados da base padrão que correspondem às strings no código de Hamming [7,4,3][7,4,3]. (É claro que o espaço do código para este código também inclui combinações lineares desses 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}

Agora podemos definir os códigos CSS em termos muito simples.

Definição

Um código CSS é um código estabilizador que pode ser expresso usando apenas geradores estabilizadores XX e ZZ.

Ou seja, os códigos CSS são códigos estabilizadores para os quais temos geradores estabilizadores nos quais nenhuma matriz de Pauli YY aparece, e nos quais XX e ZZ nunca aparecem no mesmo gerador estabilizador.

Para ser claro, por essa definição, um código CSS é aquele para o qual é possível escolher apenas geradores estabilizadores XX e ZZ — mas devemos ter em mente que há liberdade na escolha dos geradores estabilizadores para códigos estabilizadores. Portanto, geralmente haverá diferentes escolhas para os geradores estabilizadores de um código CSS que não são geradores estabilizadores XX ou ZZ (além de pelo menos uma escolha para a qual são).

Aqui está um exemplo muito simples de um código CSS que inclui tanto um gerador estabilizador ZZ quanto um gerador estabilizador XX:

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

É evidente que este é um código CSS, pois o primeiro gerador estabilizador é um gerador estabilizador ZZ e o segundo é um gerador estabilizador XX. Claro, um código CSS também deve ser um código estabilizador válido — o que significa que os geradores estabilizadores devem comutar, formar um conjunto gerador mínimo e fixar pelo menos um vetor de estado quântico. Esses requisitos são simples de verificar para este código. Como observamos na lição anterior, o espaço do código para este código é o espaço unidimensional gerado pelo estado de Bell ϕ+\vert\phi^+\rangle. O fato de que ambos os geradores estabilizadores fixam esse estado é evidente considerando as duas expressões a seguir de um e-bit, juntamente com uma interpretação desses geradores estabilizadores como verificações de paridade nas bases {0,1}\{\vert 0\rangle, \vert 1\rangle\} e {+,}\{\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}}

O código de Steane de 7 qubits é outro exemplo de 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}

Aqui temos três geradores estabilizadores ZZ e três geradores estabilizadores XX, e já verificamos que este é um código estabilizador válido.

E o código de Shor de 9 qubits é outro exemplo.

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}

Desta vez, temos seis geradores estabilizadores ZZ e apenas dois geradores estabilizadores XX. Isso é válido — não precisa haver equilíbrio ou simetria entre os dois tipos de geradores (embora frequentemente haja).

Mais uma vez, é fundamental que os códigos CSS sejam códigos estabilizadores válidos e, em particular, cada gerador estabilizador ZZ deve comutar com cada gerador estabilizador XX. Portanto, nem toda coleção de geradores estabilizadores XX e ZZ define um código CSS válido.

Detecção e correção de erros

Com relação à detecção e correção de erros, os códigos CSS em geral têm uma característica semelhante à do código de Shor de 9 qubits: os erros XX e ZZ podem ser detectados e corrigidos de forma completamente independente; os geradores estabilizadores ZZ descrevem um código que protege contra inversões de bit, e os geradores estabilizadores XX descrevem um código que protege independentemente contra inversões de fase. Isso funciona porque os geradores estabilizadores ZZ necessariamente comutam com os erros ZZ, bem como com as operações ZZ aplicadas como correções, portanto são completamente alheios a ambos, e o mesmo vale para os geradores estabilizadores XX, erros e correções.

Como exemplo, vamos considerar o 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}

A ideia básica para este código é agora evidente: é um código de Hamming [7,4,3][7,4,3] para erros de inversão de bit e um código de Hamming [7,4,3][7,4,3] para erros de inversão de fase. O fato de que os geradores estabilizadores XX e ZZ comutam é talvez uma boa sorte, pois se não comutassem, este não seria um código estabilizador válido. Mas, de fato, existem muitos exemplos conhecidos de códigos lineares clássicos que produzem um código estabilizador válido quando usados de forma semelhante.

Em geral, suponha que temos um código CSS para o qual os geradores estabilizadores ZZ permitem a correção de até jj erros de inversão de bit, e os geradores estabilizadores XX permitem a correção de até kk erros de inversão de fase. Por exemplo, j=1j = 1 e k=1k = 1 para o código de Steane, dado que o código de Hamming [7,4,3][7,4,3] pode corrigir uma inversão de bit. Segue-se então, pela discretização de erros, que este código CSS pode corrigir qualquer erro em um número de qubits até o mínimo de jj e k.k. Isso ocorre porque, quando a síndrome é medida, um erro arbitrário nesse número de qubits colapsa probabilisticamente em alguma combinação de erros XX, erros ZZ, ou ambos — e então os erros XX e ZZ são detectados e corrigidos independentemente.

Em resumo, desde que tenhamos dois códigos lineares clássicos (ou duas cópias de um único código linear clássico) que sejam compatíveis, no sentido de que definem geradores estabilizadores XX e ZZ que comutam, o código CSS que obtemos ao combiná-los herda as propriedades de correção de erros desses dois códigos, no sentido acabado de descrever.

Note que há um preço a ser pago, porém: não podemos codificar tantos qubits quanto poderíamos codificar bits com os dois códigos clássicos. Isso ocorre porque o número total de geradores estabilizadores para o código CSS é a soma do número de verificações de paridade dos dois códigos lineares clássicos, e cada gerador estabilizador reduz a dimensão do espaço do código pela metade. Por exemplo, o código de Hamming [7,4,3][7,4,3] permite a codificação de quatro bits clássicos, pois temos apenas três strings de verificação de paridade para esse código, enquanto o código de Steane de 7 qubits codifica apenas um qubit, pois tem seis geradores estabilizadores.

Espaços de código dos códigos CSS

A última coisa que faremos nesta discussão sobre códigos CSS é considerar os espaços de código desses códigos. Isso nos dará a oportunidade de examinar em maior detalhe a relação que deve existir entre dois códigos lineares clássicos para que sejam compatíveis, no sentido de que podem ser combinados para formar um código CSS.

Considere qualquer código CSS em nn qubits, e seja z1,,zsΣnz_1, \ldots, z_s \in \Sigma^n as strings de verificação de paridade de nn bits que correspondem aos geradores estabilizadores ZZ deste código. Isso significa que o código linear clássico descrito apenas pelos geradores estabilizadores ZZ, que chamaremos de CZ,\mathcal{C}_Z, tem a seguinte 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\}

Em palavras, o código linear clássico CZ\mathcal{C}_Z contém todas as strings cujo produto escalar binário com cada uma das strings de verificação de paridade z1,,zsz_1, \ldots, z_s é zero.

De forma análoga, tomemos x1,,xtΣnx_1,\ldots,x_t\in\Sigma^n como as strings de verificação de paridade de nn bits correspondentes aos geradores estabilizadores XX do nosso código. Assim, o código linear clássico correspondente aos geradores estabilizadores XX tem 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\}

Os geradores estabilizadores XX por si sós descrevem, portanto, um código semelhante a este, mas na base {+,}\{\vert {+}\rangle,\vert {-}\rangle\} em vez da base padrão.

Agora introduziremos dois novos códigos lineares clássicos derivados das mesmas escolhas de strings, z1,,zsz_1,\ldots,z_s e x1,,xt,x_1,\ldots,x_t, mas onde tomamos essas strings como geradores em vez de strings de verificação de paridade. Em particular, obtemos estes dois 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}

Esses são conhecidos como os códigos duais dos códigos definidos anteriormente: DZ\mathcal{D}_Z é o código dual de CZ\mathcal{C}_Z e DX\mathcal{D}_X é o código dual de CX.\mathcal{C}_X. Pode não estar claro neste ponto por que esses códigos duais são relevantes, mas eles se mostram bastante relevantes por múltiplas razões, incluindo as duas razões explicadas nos parágrafos a seguir.

Primeiro, as condições que devem ser satisfeitas para que dois códigos lineares clássicos CZ\mathcal{C}_Z e CX\mathcal{C}_X sejam compatíveis, no sentido de que podem ser combinados para formar um código CSS, podem ser descritas em termos simples referindo-se aos códigos duais. Especificamente, deve ser que DZCX,\mathcal{D}_Z\subseteq\mathcal{C}_X, ou equivalentemente, que DXCZ.\mathcal{D}_X\subseteq\mathcal{C}_Z. Em palavras, o código dual DZ\mathcal{D}_Z inclui as strings correspondentes aos geradores estabilizadores ZZ, e sua contenção em CX\mathcal{C}_X é equivalente ao produto escalar binário de cada uma dessas strings com as correspondentes aos geradores estabilizadores XX ser zero. Isso, por sua vez, é equivalente a cada gerador estabilizador ZZ comutar com cada gerador estabilizador XX. Alternativamente, invertendo os papéis dos geradores estabilizadores XX e ZZ e partindo da contenção DXCZ,\mathcal{D}_X\subseteq\mathcal{C}_Z, podemos chegar à mesma conclusão.

Segundo, referindo-nos aos códigos duais, podemos descrever facilmente os espaços de código de um dado código CSS. Em particular, o espaço de código é gerado por vetores da seguinte 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$)}

Em palavras, esses vetores são superposições uniformes sobre as strings no código dual DX\mathcal{D}_X do código correspondente aos geradores estabilizadores XX, deslocadas por (em outras palavras, com XOR bit a bit com) strings no código CZ\mathcal{C}_Z correspondente aos geradores estabilizadores ZZ. Para ser claro, diferentes escolhas para o deslocamento — representado pela string uu nesta expressão — podem resultar no mesmo vetor. Portanto, esses estados não são todos distintos, mas coletivamente geram todo o espaço de código.

Aqui está uma explicação intuitiva de por que tais vetores estão no espaço de código e o geram. Considere o estado da base padrão de nn qubits u,\vert u\rangle, para alguma string arbitrária de nn bits u,u, e suponha que projetamos esse estado no espaço de código. Ou seja, denotando por Π\Pi a projeção no espaço de código do nosso código CSS, considere o vetor Πu.\Pi\vert u\rangle. Há dois casos:

  • Caso 1: uCZ.u\in\mathcal{C}_Z. Isso implica que cada gerador estabilizador ZZ do nosso código CSS age trivialmente sobre u.\vert u\rangle. Os geradores estabilizadores XX, por outro lado, simplesmente invertem alguns dos bits de u.\vert u\rangle. Em particular, para cada gerador vv de DX,\mathcal{D}_X, o gerador estabilizador XX correspondente a vv transforma u\vert u\rangle em uv.\vert u\oplus v\rangle. Caracterizando a projeção Π\Pi como a média sobre os elementos do estabilizador (como vimos na lição anterior), obtemos esta 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. Isso implica que pelo menos uma das verificações de paridade correspondentes aos geradores estabilizadores ZZ falha, ou seja, u\vert u\rangle deve ser um autovetor de 1-1 de pelo menos um dos geradores estabilizadores ZZ. O espaço de código do código CSS é a interseção dos autoespaços de +1+1 dos geradores estabilizadores. Portanto, como autovetor de 1-1 de pelo menos um dos geradores estabilizadores ZZ, u\vert u\rangle é ortogonal ao espaço de código:

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

E agora, ao percorrermos todas as strings uu de nn bits, descartarmos aquelas para as quais Πu=0\Pi\vert u\rangle = 0 e normalizarmos as demais, obtemos os vetores descritos anteriormente, o que demonstra que eles geram o espaço de código.

Também podemos usar a simetria entre os geradores estabilizadores XX e ZZ para descrever o espaço de código de uma forma semelhante, mas diferente. Em particular, é o espaço gerado por vetores da seguinte 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$)}

Em essência, XX e ZZ foram trocados em cada instância em que aparecem — mas também devemos trocar a base padrão pela base {+,}\{\vert+\rangle,\vert-\rangle\}, razão pela qual as operações de Hadamard estão incluídas.

Como exemplo, vamos considerar o código de Steane de 7 qubits. As strings de verificação de paridade para os geradores estabilizadores XX e ZZ são as mesmas: 1111000,1111000, 1100110,1100110, e 1010101.1010101. Os códigos CX\mathcal{C}_X e CZ\mathcal{C}_Z são, portanto, os mesmos; ambos são iguais ao 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\}

Os códigos duais DX\mathcal{D}_X e DZ\mathcal{D}_Z são, portanto, também os mesmos. Temos três geradores, portanto obtemos oito 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\}

Essas strings estão todas contidas no código de Hamming [7,4,3][7,4,3], portanto a condição CSS é satisfeita: DZCX,\mathcal{D}_Z \subseteq \mathcal{C}_X, ou equivalentemente, DXCZ.\mathcal{D}_X \subseteq \mathcal{C}_Z.

Dado que DX\mathcal{D}_X contém metade de todas as strings em CZ,\mathcal{C}_Z, há apenas dois vetores distintos uDX\vert u\oplus \mathcal{D}_X\rangle que podem ser obtidos escolhendo uCZ.u\in\mathcal{C}_Z. Isso é esperado, pois o código de Steane de 7 qubits tem um espaço de código bidimensional. Podemos usar os dois estados que obtemos dessa forma para codificar o estado lógico 0\vert 0\rangle e 1\vert 1\rangle da seguinte maneira.

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 costume, essa escolha não é obrigatória — somos livres para usar o espaço de código para codificar qubits como quisermos. Essa codificação é, no entanto, consistente com o exemplo de um circuito de codificação para o código de Steane de 7 qubits apresentado na lição anterior.