Correção de erros
Provavelmente você já enfrentou problemas com erros de comunicação. É muito
comum não entender alguma coisa que você ouve alguém dizer. Quantas vezes
você já teve que repetir algo que acabou de falar?
Há erros na comunicação
sempre que a mensagem que você intenciona enviar acaba chegando com erros
ao seu destino.
Existem também erros que você comete na hora de enviar
e na hora de receber e interpretar uma mensagem.
O meio através do qual
uma mensagem caminha é tipicamente chamado de canal de comunicação ou,
simplesmente, canal. Quando acontecem erros aleatórios durante a transmissão
de uma mensagem, dizemos que o canal é ruidoso.
Supondo que o envio e a
recepção de uma mensagem sejam sempre exatos, sem ocorrência alguma de
erros, como corrigir os erros que ocorrem durante a transmissão através de um
canal ruidoso?
Para começar a responder essa questão, vamos considerar um casal, Alice e
Bob (ao invés de
A
e
B ),
e vamos supor que ela envia uma mensagem para ele.
Para simplicar e tornar a discussão mais divertida, suponhamos que a Alice
precisa dizer se vai ou não sair hoje e se quer ou não a companhia do Bob. Para
ele, entender a mensagem sem ambiguidade é muito importante, pois, caso ela
vá sair e queira sua companhia, ele terá que tomar um banho e se arrumar,
talvez até fazer a barba, e ir apanhá-la (já que é um cavalheiro). Agora, caso
ela não vá sair, mas queira a companhia dele, também é aconselhável que ele se
apresente bem arrumadinho e cheiroso na casa dela. No entanto, caso ela não
queira sua companhia, o Bob pode car barbudo e à vontade, cheirando mal,
em sua casa. Nessas circunstâncias, ele pode, além de tudo, encher a cara, caso
a Alice vá sair, ou pode tranquilizar-se e assistir a um lme, caso não vá sair,
imaginando que talvez ela esteja apenas com dor de cabeça. Você pode imaginar
o que aconteceria se ele recebesse uma mensagem errada? Por exemplo, se ela
enviasse a mensagem, Vou sair, quero sua companhia, e ele entendesse, Vou
sair, não quero sua companhia, quais poderiam ser as consequências?
Bem,
primeiro, ele não tomaria banho, não faria a barba, caria frustrado e com
ciúmes dela, além, é claro, de se embebedar. Ela, esperando por ele, começaria
a car preocupada e decidiria ir até sua casa para ver se está tudo bem. Imagine
a cena do encontro!
Para matematizar o problema, vamos codicar as possíveis mensagens. A
Alice pode ou não sair, o que pode ser representado por apenas um bit:
caso armativo, e
0, no caso negativo.
1,
no
Além disso, ela pode, independentemente
de sair ou não, querer ou não a companhia do Bob, o que também pode ser
representando por apenas um bit:
1,
no caso armativo, e
0,
no caso negativo.
Uma mensagem completa possui, portanto, dois bits e há um universo de quatro
possibilidades:
00, 01, 10
e
11.
Em uma tabela, que o Bob deve estar sempre
carregando com ele, temos a codicação representada assim:
1
Mensagem
Código
Não vou sair, não quero sua companhia.
00
01
10
11
Não vou sair, quero sua companhia.
Vou sair, não quero sua companhia.
Vou sair, quero sua companhia.
.
Note que se o canal é ruidoso, sempre que um só bit for trocado, uma mensagem, ou palavra, do código torna-se outra palavra do mesmo código.
exemplo, se a palavra
11,
Por
durante a transmissão pelo canal, sofrer um erro no
segundo bit, então o Bob receberá a palavra
10,
que é outra palavra, ou men-
sagem, do código; não há como ele saber que houve um erro de transmissão e,
com isso, congurar-se-á a situação embaraçosa do exemplo acima. Se dois bits
forem trocados durante a transmissão, novamente não há como o Bob saber que
houve erros no canal.
A solução está em usar redundância na codicação de mensagens. Isso pode
acabar custando mais caro. Veja você que a transmissão de mensagens tem um
custo; basta você enviar um torpedo (SMS) pelo celular que a operadora cobrará
uma tarifa. Se o número de caracteres passar de
255
(GSM) ou
160
(CDMA),
você pagará mais do que uma só tarifa. Então, no mundo hipotético de Alice
e Bob, vamos supor que ela não quer usar muitos bits redundantes, pois quer
manter seus custos com mensagens curtas sucientemente baixos. No entanto,
como vimos, com dois bits apenas não dá para o Bob saber se houve ou não um
erro de transmissão. Para economizar, vamos ver o que dá para fazer com três
bits. Como codicar palavras de dois bits usando palavras de três bits?
Note que as palavras
a segunda,
1's.
2.
00
e
Já as palavras
11 têm um número par de 1's: a primeira tem 0 e
01 e 10 têm um só 1, isto é, um número ímpar de
Vamos, então, introduzir um bit a mais para indicar a paridade da palavra
e vamos posicioná-lo como o primeiro bit de palavras com três bits.
quando a palavra original, de dois bits, for par, como
primeiro bit par, isto é,
000
e
011,
0,
00
e
11,
Assim,
utilizaremos o
nas palavras de três bits correspondentes, ou seja,
respectivamente. Já as palavras ímpares,
palavras de três bits cujo primeiro bit é
1,
101
isto é,
01 e 10, corresponderão a
110, respectivamente. A
e
tabela correspondente às mensagens agora ca assim:
Palavra de dois bits
Palavra de três bits
00
01
10
11
000
101
110
011
.
Usando essa tabela, dá para o Bob determinar se a mensagem que recebe está
correta ou errada? Vejamos um exemplo: suponha que a Alice manda a mensagem do exemplo acima, usando três bits, de acordo com o código da tabela
acima, isto é, ela envia a palavra
011.
Se ocorrer o erro do exemplo, ou seja,
se o terceiro bit for trocado durante a transmissão, o Bob receberá a palavra
010.
Veja que essa palavra não corresponde ao código exposto na tabela acima!
Nesse caso o Bob saberá que houve algum erro no canal. Note, porém, que ele
não saberá qual bit está errado. Dizemos que o código acima permite a detecção
2
de, no máximo, um erro, sem permitir correção. Não dá, com esse código, para
011, sofrer um
110, que está no
detectar dois ou três erros. Por exemplo, se a palavra enviada,
erro no primeiro e no terceiro bits, o Bob receberá a palavra
código e, assim, ele vai se colocar em uma situação complicada novamente. O
que normalmente acontece é que um canal pode ser ruidoso com a probabilidade de ocorrer um erro maior do que a probabilidade de dois erros. Então, o
Bob pode, até um certo ponto, apostar que uma determinada mensagem esteja
correta, já que está no código, sempre cando, porém, com a pulga atrás da
orelha... Talvez fosse interessante ver o que é possível fazer com mais um bit
de redundância. Mas antes, deixe-me apresentar a nomenclatura que usaremos
para códigos. Como na tabela acima codicamos palavras de dois bits usando
palavras de três bits, dizemos que esse é um código
dizemos que temos um código
ando palavras de
código
n
[n, k]
[3, 2] .
De maneira geral,
quando codicamos palavras de
bits, sempre com
n > k.
k
bits, us-
Então, como podemos obter um
[4, 2]?
Uma maneira possível de obter redundância é repetir os bits. Assim, podemos codicar as palavras originais, de dois bits, em palavras de quatro bits tais
que os dois primeiros bits sejam iguais ao primeiro bit da palavra original e os
dois últimos bits sejam iguais ao segundo bit da palavra original. Usando uma
tabela, temos
Palavra original
Palavra codicada
00
01
10
11
0000
0011
1100
1111
.
Será que o Bob pode usar essa redundância de dois bits extras para detectar e
corrigir erros? Infelizmente, usando esse código ele só consegue detectar, com
certeza, apenas um erro no máximo e não consegue corrigir, com certeza, erro
algum. Por exemplo, se a palavra enviada for
1100
e ocorrer apenas um erro,
1000 e ele detectará
1000 não pertence ao código, mas não saberá se a palavra correta
0000, mesmo que tenha certeza que apenas um erro tenha ocorrido.
digamos, no segundo bit, então o Bob receberá a palavra
um erro, pois
é
1100,
ou
Se ocorrerem dois erros, de novo a palavra voltará a ser igual a uma outra da
tabela e o Bob não detectará erro algum.
A tabela acima representa apenas
um possível código com quatro bits. Não há uma outra codicação mais ecaz,
permitindo detectar mais erros e talvez até corrigi-los?
Para procurar por códigos possíveis, é interessante formular matematicamente o problema.
Veja que o código acima nada mais é do que uma trans-
formação de palavras de dois bits em palavras de quatro bits.
Para tratar
transformações desse tipo, podemos tentar pensar em vetorizar as palavras, isto
é, podemos tentar a representação de cada palavra por um vetor coluna. Assim,
por exemplo, podemos escrever
00
como
3
0
0
,
01
0
1
1
0
1
1
como
10
como
,
e
11
como
.
Note que as componentes desses vetores são sempre
0 ou 1, já que os signicados
desses números são não e sim, respectivamente; não haveria como interpretar
uma componente igual a
2
em um desses vetores represntando palavras. Com
esse tipo de notação, podemos ver que a tabela acima com um particular código
[4, 2]
é uma transformação representada por uma matriz
4 × 2,
matriz geratriz, dada por

G =
1
 1

 0
0

0
0 
.
1 
1
Veja só como é verdade:

G
0
0
que representa a palavra
1
 1
= 
 0
0
G
que representa


0 0
 0
0 
0

=
 1
1  1
1
1



0 1
 1
0 
1

=
 0
1  0
1
0



0 1
 1
0 
1

=
 1
1  1
1
1


,

0
1
1
0
1
1
1
 1
= 
 0
0

,

0011

G
representando

0000,



0
0  0
0 
0

=
 0
1  0
0
1
1100,
1
 1
= 
 0
0

,

e

G
1
 1
= 
 0
0
4

,

chamada de
1111. Vemos que a matriz G gera a codicação da tabela
[4, 2] , basta trocarmos os
elementos da matriz G. Mas agora temos um probleminha: vamos supor que
queiramos modicar somente a primeira linha da matriz G e escrever


1 1
 1 0 

G1 = 
 0 1 .
0 1
que equivale à palavra
acima.
Logo, para obter outros códigos, do tipo
Veja o que acontece se aplicamos a transformação

1
1
G1
Se somarmos
1
com
1

1
 1
= 
 0
0
e obtivermos
G1

na palavra
11 :

1 1+1
 1 
0 
1


=
 1 .
1  1
1
1
2,
sentar uma palavra, já que o número
obteremos um vetor que não pode repre-
2
não signica sim, nem não. Temos
que eliminar a possibilidade de outros números aparecerem, que não sejam apenas
0
e
1.
2. Para as componentes
2, que é assim:
A saída para isso é usar somas módulo
palavras, vamos sempre usar a aritmética módulo
0+0
=
0,
0+1
=
1,
1+0
=
1
1+1
=
0.
de
e
Agora estamos equipados para modicar a matriz geratriz e gerar outros códigos
[4, 2] .
No exemplo acima, portanto, obtemos

G1
1
1
1
 1
= 
 0
0


0
1  1
0 
1

=
 1
1  1
1
1


.

Veja uma coisa interessante sobre uma matriz geratriz com as duas colunas
iguais:

G2
1
1
=


1 0
 0
0 
1

=
 0
1  1
1
0
1
 0

 1
1
5




e

G2
0
0
1
 0
= 
 1
1


0
1  0
0 
0

=
 0
1  0
0
1


,

isto é, a matriz

G2
1
 0
= 
 1
1

1
0 

1 
1
transforma duas palavras de dois bits diferentes em duas palavras de quatro bits
iguais!
Isso causa muita confusão, pois não dá para decodicar uma palavra
dessas, já que nunca saberemos se
0000 quer dizer 11 ou 00. Logo,
não podemos
ter duas colunas iguais para nossas geratrizes.
Outra propriedade interessante de geratrizes é que trocar uma de suas colunas pela soma módulo
2
das duas colunas originais não altera o código. Por
exemplo, tomemos a matriz
G
e troquemos sua primeira coluna pela soma de
G3 ,

1
  1
=
  1
1
suas colunas originais, obtendo a nova geratriz

G3
1+0
 1+0
= 
 0+1
0+1
0
0
0
1
1
0
1
1
0
0
1
1

dada por

0
0 
.
1 
1
Com isso, obtemos

G3
1
 1

= 
1
1

G3
1
 1
= 
 1
1

G3
1
 1
= 
 1
1


0 0

0 
 0 = 0
 0
1  0
1
0



0
0  0
0 
0

=
 1
1  1
1
1



0 1
 1
0 
1

=
 1
1  0
1
1



0 1
 1
0 
1

=
 0
1  1
1
0


,


,


,

e

G3
1
 1
= 
 1
1
6

,

que, embora tenha alterado a regra de correspondência biunívoca entre as
palavras, não muda as palavras do código de quatro bits, isto é, as mesmas
palavras
0000, 0011, 1100
1111
e
G3 .
[4, 2] , pode-
continuam sendo geradas pela geratriz
Com as propriedades que aprendemos sobre geratrizes de códigos
mos dizer que essas matrizes, para serem úteis, devem ter duas colunas que sejam
linearmente independentes, isto é, uma não pode ser igual à outra, nesse tipo
particular de código. Então, essas duas colunas servem como uma base para um
subespaço de duas dimensões de um espaço vetorial de quatro dimensões. Note
que esses espaços vetoriais são espaços de vetores coluna construídos apenas com
0
componentes
módulo
2
e
1
e utilizando aritmética módulo
2.
Note também que a soma
de dois vetores coluna quaisquer do código resulta em outro vetor do
código, ilustrando que o conjunto é mesmo um subespaço vetorial.
Vamos denir o produto escalar entre dois vetores de um mesmo espaço
vetorial de palavras de código de forma análoga à usual, em que tomamos a
soma módulo
2
dos produtos das componentes dos vetores.
O produto entre
duas componentes é como o usual, não havendo mudança no caso de aritmética
módulo
2,
pois só há multiplicações entre os números do conjunto
essa denição, é fácil ver que a palavra
1100,
{0, 1} .
Com
por exemplo, é ortogonal a ela
mesma, já que o produto escalar de seu vetor coluna por ele mesmo é nulo.
Agora sabemos gerar códigos
uma matriz geratriz
n×k
[n, k] quaisquer, já que só precisamos construir
k colunas linear-
e tomar o cuidado para escolher
mente independentes, isto é, nenhuma dessas colunas pode ser igual à soma de
qualquer número das outras
k−2
colunas, onde, entre as colunas, não estamos
considerando o vetor nulo (por isso escrevi k − 2 outras colunas e não k − 1.)
Com esse formalismo, agora queremos descobrir uma maneira de testar se uma
determinada palavra pertence ou não a um dado código
C.
É evidente que uma
palavra do código não pode ter componente alguma em um subespaço ortogonal
C, que é
C e denotado por C ⊥ . Seja C o código original das
quatro palavras, 0000, 0011, 1100 e 1111. Vamos agora considerar o conjunto
de todas as palavras de quatro bits simultaneamente ortogonais (módulo 2) às
quatro palavras de C. Então, queremos encontrar todos os vetores coluna do
àquele de
C.
Então, vamos gerar um subespaço ortogonal ao do código
chamado de código dual de
tipo


a1
 a2 


 a3  ,
a4
com
a1 , a2 , a3
e
a4
pertencentes ao conjunto
t 
a1
0
 a2   0

 
 a3   1
a4
1

7
{0, 1} ,




=
0,
tais que
t 
1
a1
 a2   1

 
 a3   0
0
a4

t 
a1
1
 a2   1

 
 a3   1
a4
1





=
0
=
0,
e

onde o sobrescrito
qualquer.
t



signica que estamos tomando a transposta de uma matriz
a1 , a2 , a3
Então, devemos encontrar
e
a4
simultaneamente satis-
fazendo
a3 + a4
=
0
a1 + a2
=
0.
e
Com essas duas equações satisfeitas, também teremos a equação
a1 + a2 + a3 + a4
=
automaticamente satisfeita. Em aritmética módulo
a3
=
a3
= a4 = 1,
a1
=
a1
= a2 = 1.
0
2, podemos ter, como solução,
a4 = 0
ou
além de também ter
a2 = 0
ou
As palavras formadas com essas possíveis soluções para suas componentes cam:
0000, 0011, 1100 e 1111, isto é, obtemos o mesmo código C como sendo ortogonal
C ⊥ = C. Como esses dois
códigos são o mesmo, têm a mesma geratriz G. Como as colunas de G geram o
subespaço ortogonal a C, que no presente caso é o próprio C, essas colunas são
ortogonais a todas as palavras de C. Logo, para testar se uma dada palavra é
do código, basta calcularmos o produto da transposta de G pelo vetor coluna
a si próprio e, portanto, é dito auto-dual, ou seja,
representando a palavra em questão; se o resultado não for nulo, segue que a
8
palavra não está no código e, portanto, um erro é detectado. Por exemplo, caso
o Bob receba a palavra
1000, ele pode ver que essa palavra não é do código pelo
produto matricial seguinte:


1
 0 

Gt 
 0  =
0

1
0
1
0
0
1
0
1

1
 0 

= 1 ,
 0 
0
0
que é diferente do vetor nulo de duas dimensões.
No caso de um código geral, do tipo
[n, k] ,
a matriz transposta da geratriz
do código dual é chamada de matriz de vericação de paridade e, normalmente,
é denotada por
H. Creio que esta postagem está comprida o bastante para fazer
uma pausa. Minha intenção é continuar a desenvolver este assunto apenas se
você realmente tiver curiosidade suciente para deixar comentários.
aguardando!
9
Estarei
Download

Uma versão em PDF