MATH2400 4,832 words·25 min read

Codes

Why Errors Need Detecting#

In Cryptosystems the whole point was privacy; we wanted a message that an eavesdropper could not read. Sometimes we are much less worried about privacy and much more worried about the message arriving intact. Wires pick up noise, discs get scratched, satellites get hit by cosmic rays; digits flip. What we want is a way of writing the message down so that a flipped digit is at least noticeable, and ideally repairable.

To see why this is a genuine problem, take the standard letter-to-number conversion A→1A \to 1, B→2B \to 2, C→3,…C \to 3, \dots and send the letter MM. Then M→13M \to 13, and (recalling Base Number Systems) 1313 in binary is

13=8+4+1=(1101)2,13 = 8 + 4 + 1 = (1101)_2,

so we transmit the string 11011101. Now suppose the leading digit gets knocked from 11 to 00 in transit, so the receiver sees 01010101. They decode this perfectly happily:

(0101)2=4+1=5→E.(0101)_2 = 4 + 1 = 5 \to E.

The receiver reads EE, believes it, and has absolutely no reason to suspect anything went wrong. This is the failure mode we are trying to design away. The problem is not that an error occurred; the problem is that every one of the sixteen 44-digit strings is a legal message, so a corrupted string is still a legal message.

The fix, in every code in this lecture, is the same idea: deliberately send more digits than the message needs, arranged so that only some of the strings are legal. Then a single flip drops you off the list of legal strings and the receiver can see it. Codes come in two strengths:

  • an error-detecting code lets the receiver tell that something has gone wrong (so they can ask for a retransmission);
  • an error-correcting code lets the receiver work out which digit is wrong and repair it without asking for anything.

All the arithmetic in this lecture happens in Z2={0,1}\mathbb{Z}_2 = \{0, 1\}, which by Rings and Fields is a field, and in which the only rules you need are

0+0=0,0+1=1+0=1,1+1=0.0 + 0 = 0, \quad 0 + 1 = 1 + 0 = 1, \quad 1 + 1 = 0.

Basically, addition in Z2\mathbb{Z}_2 is "flip the digit if you add 11, leave it alone if you add 00", and it is its own inverse: −1=1-1 = 1, so in Z2\mathbb{Z}_2 there is no difference between adding and subtracting, and you never have to worry about signs. That single fact makes every calculation below shorter than it looks.

Parity Check Codes#

The cheapest possible thing you can do is add one extra digit that records whether the message had an even or odd number of 11s.

Note

Definition (Simple Parity Check Code)
Encoding. Convert the message to binary, and then append an extra check digit that is either 00 if there are an even number of 11s in the original binary message, or 11 if there are an odd number of 11s in the original binary message.

Decoding. Count the number of 11s in the encoded message. If there are an odd number of 11s, at least one error must have occurred. When reading the message, ignore the final digit.

Basically, the check digit is chosen to make the total number of 11s even; so if the receiver ever counts an odd number of 11s, a digit must have flipped. Said in Z2\mathbb{Z}_2, if the message digits are m1,m2,…,mkm_1, m_2, \dots, m_k then the check digit is simply

mk+1=m1+m2+⋯+mk in Z2,m_{k+1} = m_1 + m_2 + \cdots + m_k \text{ in } \mathbb{Z}_2,

and a legal encoded word is exactly one satisfying m1+m2+⋯+mk+mk+1=0m_1 + m_2 + \cdots + m_k + m_{k+1} = 0 in Z2\mathbb{Z}_2. Keep that phrasing in mind; every code in this lecture will turn out to be "the strings satisfying some system of Z2\mathbb{Z}_2 equations".

Example. Encode the letter MM with a simple parity check, and show what happens when the leading digit is flipped in transit.
As above, M→13→1101M \to 13 \to 1101. The original message 11011101 contains three 11s, which is odd, so the check digit is 11 and the transmitted word is

11011.11011.

Suppose the leading digit is flipped, so the receiver gets 0101101011. Counting,

0+1+0+1+1=3,\begin{align*} 0 + 1 + 0 + 1 + 1 &= 3, \end{align*}

which is odd; therefore the receiver knows that at least one error has occurred and can request a retransmission. Contrast this with the bare 44-digit code, where the same flip silently turned MM into EE; one extra digit bought us the ability to notice.

Example. The same word 1101111011 is sent, but this time the first two digits are flipped, so the receiver gets 0001100011. What happens?
Counting the 11s,

0+0+0+1+1=2,\begin{align*} 0 + 0 + 0 + 1 + 1 &= 2, \end{align*}

which is even, so the parity check passes and the receiver suspects nothing. They discard the final digit and read 0001=1→A0001 = 1 \to A. Therefore, the parity check completely misses this pair of errors and silently reports the letter AA instead of MM. A parity check detects exactly an odd number of errors; any even number of errors cancels out and slips through unnoticed.

It is worth being blunt about the other limitation as well. Even when the check does fire, all it tells you is "somewhere in these five digits, an odd number of things are wrong". It does not tell you where, and it does not tell you how many, so there is nothing you can do except ask for the message again. The simple parity check is a pure error-detecting code; it can never correct anything.

The cost of the code is one extra digit per chunk. If we parity-check in chunks of 44 information digits, then 55 digits get transmitted for every 44 digits of actual message, so 45\tfrac45 of the traffic is useful; we will call this proportion the rate of the code. A rate of 45\tfrac45 is excellent value, which is precisely why parity bits are everywhere in real hardware. The trouble is that we got what we paid for: cheap code, weak guarantees.

Reduplication Codes#

The obvious way to buy more protection is brute force; just say everything twice.

Note

Definition (Double Reduplication Code)
Encoding. Convert the message to binary, repeating every digit twice.

Decoding. When reading the message, interpret every pair of digits as a single digit. If the pair of digits is 0000, read this as 00, and if the pair of digits is 1111, read this as 11. If the pair of digits is 0101 or 1010, we know (at least) one error must have occurred at this position in the message.

Basically, the legal pairs are 0000 and 1111; anything else is a red flag, and it even tells you which pair went wrong. This is strictly better than a parity check in one respect and strictly worse in another, so it is worth being careful about exactly what it gives you.

Example. Encode M→1101M \to 1101 under double reduplication, and decode the received word 1110001111100011.
Repeating each digit twice, the transmitted word is

1101⟶11 11 00 11.1101 \longrightarrow 11\ 11\ 00\ 11.

The receiver gets 11 10 00 1111\ 10\ 00\ 11. Splitting into pairs and reading them off,

11→1,10→error in this position,00→0,11→1.\begin{align*} 11 &\to 1, \\ 10 &\to \text{error in this position}, \\ 00 &\to 0, \\ 11 &\to 1. \end{align*}

Therefore, the receiver knows that an error occurred, and knows it happened in the second digit of the message — but that is as far as it goes. The true second digit could have been a 11 (with the second copy flipped) or a 00 (with the first copy flipped), and nothing in the received word distinguishes those two stories. Double reduplication detects and locates an error, but it still cannot correct one.

Notice also that multiple errors are often, but not always, caught: two errors in different pairs both show up, whereas two errors inside the same pair turn 1111 back into 0000 and are invisible. In exchange for all this we have doubled the length of the message, so the rate has crashed from 45\tfrac45 to 12\tfrac12. That is a lot of bandwidth for a code that still cannot fix anything.

If saying everything twice does not let you correct, the natural next move is to say everything three times and take a vote.

Note

Definition (Triple Reduplication Code)
Encoding. Convert the message to binary, repeating every digit three times.

Decoding. When reading the message, interpret every triple of digits as a single digit. If the triple of digits contains at least two 00s, read this as 00, and if the triple of digits contains at least two 11s, read this as 11. Whenever a triple is not 000000 or 111111, we know (at least) one error has occurred, and can fairly reliably correct the error.

Basically, this is majority rule: each digit gets three votes, and the minority is assumed to be the mistake. The correction is only valid under the assumption that there is at most one error per triple; if two digits inside the same triple flip, the majority vote confidently returns the wrong answer, which is worse than not correcting at all.

Example. Encode M→1101M \to 1101 under triple reduplication, and decode the received word 111 101 000 011111\ 101\ 000\ 011.
Repeating each digit three times, the transmitted word is

1101⟶111 111 000 111,1101 \longrightarrow 111\ 111\ 000\ 111,

which is 1212 digits long. Splitting the received word into triples and taking a majority vote in each,

111→1(unanimous),101→1(two 1s, so the middle digit was flipped),000→0(unanimous),011→1(two 1s, so the first digit was flipped).\begin{align*} 111 &\to 1 \quad (\text{unanimous}), \\ 101 &\to 1 \quad (\text{two } 1\text{s, so the middle digit was flipped}), \\ 000 &\to 0 \quad (\text{unanimous}), \\ 011 &\to 1 \quad (\text{two } 1\text{s, so the first digit was flipped}). \end{align*}

Therefore, the decoded message is 1101=13→M1101 = 13 \to M, recovered correctly despite two transmission errors, and the receiver can even point at exactly which two digits were wrong. This is a genuine error-correcting code.

Example. Under the same code, what does the receiver make of the received triple 110110?
Majority vote gives 11, since two of the three digits are 11. If exactly one error occurred, this is right. But if the sent triple was 000000 and two digits flipped, the true digit was 00 and the decoder has just committed confidently to the wrong value; and if the sent triple was 111111 with one flip, it is right. Therefore, the answer the code returns is 11, but that answer is only trustworthy under the at-most-one-error-per-triple assumption. Every error-correcting code in this course carries an assumption of that kind; quoting the answer without quoting the assumption is only half the answer.

The price is brutal: the rate has fallen to 13\tfrac13, so two out of every three digits you transmit are pure redundancy, and all of that only buys you one correctable error per three digits. Compare the three codes so far:

Code Rate Detects Locates Corrects
Simple parity check 45\tfrac45 odd number of errors no no
Double reduplication 12\tfrac12 one error per pair yes no
Triple reduplication 13\tfrac13 one error per triple yes yes

The obvious question is whether we can get the correcting power of the third row at anything like the rate of the first. The answer is yes, and it comes from linear algebra.

Vectors and Matrices#

Before building the good codes, we need a little machinery. Nothing here is deep; it is just a compact language for saying "this collection of digits satisfies this collection of Z2\mathbb{Z}_2 equations".

Note

Definition (Row Vector)
A real-valued row vector is a mathematical object containing an ordered list of real numbers. We write v=(v1,v2,v3)v = (v_1, v_2, v_3) for a row vector of size 1×31 \times 3, where v1,v2,v3∈Rv_1, v_2, v_3 \in \mathbb{R}.

Note

Definition (Matrix)
A real-valued matrix is an array of real numbers which can be thought of as several row vectors stacked together. We write

M=(m1,1m1,2m1,3m2,1m2,2m2,3)M = \begin{pmatrix} m_{1,1} & m_{1,2} & m_{1,3} \\ m_{2,1} & m_{2,2} & m_{2,3} \end{pmatrix}

for a matrix of size 2×32 \times 3, where each mi,j∈Rm_{i,j} \in \mathbb{R}.

Sizes are always quoted as (rows) ×\times (columns), in that order; getting this backwards is the single most common slip in matrix questions, and it makes every subsequent product illegal.

Note

Notation
The transpose of a vector or matrix, denoted by the superscript TT, is the original object with its rows converted to columns. For example, a 2×12 \times 1 column vector can be written as

(v1,v2)T=(v1v2).(v_1, v_2)^T = \begin{pmatrix} v_1 \\ v_2 \end{pmatrix}.

Note

Notation
The k×1k \times 1 zero vector is a vector all of whose entries are 00; for example the 3×13 \times 1 zero vector is 0=(0,0,0)T0 = (0,0,0)^T. The k×1k \times 1 standard basis vector eie_i is the vector whose iith entry is 11, with all other entries being 00; for example the 3×13 \times 1 standard basis vectors are

e1=(1,0,0)T,e2=(0,1,0)T,e3=(0,0,1)T.e_1 = (1,0,0)^T, \quad e_2 = (0,1,0)^T, \quad e_3 = (0,0,1)^T.

The transpose is mostly a typographical convenience here: our codewords are naturally written left-to-right as row vectors, but matrices multiply column vectors, so xTx^T is how a codeword xx gets fed into a matrix.

Multiplication is defined by "row against column". The product of a 1×k1 \times k row vector uu with a k×1k \times 1 column vector vv is the single number

uv=(u1,u2,…,uk)(v1,v2,…,vk)T=∑i=1kuivi=u1v1+u2v2+⋯+ukvk,uv = (u_1, u_2, \dots, u_k)(v_1, v_2, \dots, v_k)^T = \sum_{i=1}^{k} u_i v_i = u_1v_1 + u_2v_2 + \cdots + u_kv_k,

and to multiply two matrices AA and BB we create a new matrix ABAB whose (i,j)(i,j)th entry is the product of the iith row of AA with the jjth column of BB. The case we actually use is a matrix times a column vector: the product of an a×ba \times b matrix MM with a b×1b \times 1 column vector vv is an a×1a \times 1 vector MvMv whose kkth entry is ∑i=1bmk,ivi\sum_{i=1}^{b} m_{k,i}v_i. Written out for a 2×32 \times 3 matrix,

(m1,1m1,2m1,3m2,1m2,2m2,3)(v1v2v3)=(m1,1v1+m1,2v2+m1,3v3m2,1v1+m2,2v2+m2,3v3).\begin{pmatrix} m_{1,1} & m_{1,2} & m_{1,3} \\ m_{2,1} & m_{2,2} & m_{2,3} \end{pmatrix} \begin{pmatrix} v_1 \\ v_2 \\ v_3 \end{pmatrix} = \begin{pmatrix} m_{1,1}v_1 + m_{1,2}v_2 + m_{1,3}v_3 \\ m_{2,1}v_1 + m_{2,2}v_2 + m_{2,3}v_3 \end{pmatrix}.

Basically, each row of the matrix eats the whole vector and produces one number, so the answer has as many entries as MM has rows.

Example. What is the product of (123420)\begin{pmatrix} 1 & 2 & 3 \\ 4 & 2 & 0 \end{pmatrix} and (1,3,2)T(1,3,2)^T?
This is a 2×32 \times 3 matrix times a 3×13 \times 1 column vector, so the answer is 2×12 \times 1. Taking each row against the column in turn,

(123420)(132)=(1(1)+2(3)+3(2)4(1)+2(3)+0(2))=(1+6+64+6+0)=(1310).\begin{align*} \begin{pmatrix} 1 & 2 & 3 \\ 4 & 2 & 0 \end{pmatrix} \begin{pmatrix} 1 \\ 3 \\ 2 \end{pmatrix} &= \begin{pmatrix} 1(1) + 2(3) + 3(2) \\ 4(1) + 2(3) + 0(2) \end{pmatrix} \\ &= \begin{pmatrix} 1 + 6 + 6 \\ 4 + 6 + 0 \end{pmatrix} \\ &= \begin{pmatrix} 13 \\ 10 \end{pmatrix}. \end{align*}

Therefore, the product is (13,10)T(13, 10)^T.

For codes we do exactly this arithmetic but in Z2\mathbb{Z}_2, which is much easier: every entry of the matrix is 00 or 11, so a row against a column is just "add up the entries of the vector sitting underneath a 11, then reduce mod 22". In other words, the kkth entry of MvMv over Z2\mathbb{Z}_2 is 00 if the positions where row kk has a 11 contain an even number of 11s in vv, and 11 if they contain an odd number. Every Hamming calculation below is really a stack of parity checks in disguise.

Example. Compute MvMv over Z2\mathbb{Z}_2, where M=(101101101101)M = \begin{pmatrix} 1 & 0 & 1 & 1 \\ 0 & 1 & 1 & 0 \\ 1 & 1 & 0 & 1 \end{pmatrix} and v=(1,1,0,1)Tv = (1,1,0,1)^T.
Reading off which positions of vv each row selects,

row 1:v1+v3+v4=1+0+1=0,row 2:v2+v3=1+0=1,row 3:v1+v2+v4=1+1+1=1,\begin{align*} \text{row } 1 &: v_1 + v_3 + v_4 = 1 + 0 + 1 = 0, \\ \text{row } 2 &: v_2 + v_3 = 1 + 0 = 1, \\ \text{row } 3 &: v_1 + v_2 + v_4 = 1 + 1 + 1 = 1, \end{align*}

all in Z2\mathbb{Z}_2. Therefore, Mv=(0,1,1)TMv = (0,1,1)^T. Notice that no multiplication was ever performed; over Z2\mathbb{Z}_2 you only ever count 11s and ask whether the count is even or odd.

The Hamming (7,4) Code#

A Hamming code is a very efficient type of error-correcting code, in the sense that it minimises the number of check digits required per message while maximising the number of errors that can be detected or corrected. The smallest useful one squeezes 44 information digits into 77 transmitted digits, so it corrects a single error at a rate of 47\tfrac47 — compare that with triple reduplication, which needs 1212 digits to protect the same 44.

Everything is controlled by one matrix.

Note

Definition (Standard Hamming (7,4)(7,4) Matrix)
The Hamming (7,4)(7,4) code uses the standard Hamming (7,4)(7,4) matrix

H=(101010101100110001111),H = \begin{pmatrix} 1 & 0 & 1 & 0 & 1 & 0 & 1 \\ 0 & 1 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 \end{pmatrix},

whose columns are the integers 11 through to 77 in binary, reading from bottom to top.

That last sentence is the whole trick, so make sure you can see it. Reading each column upwards gives a 33-digit binary string, and those strings run through 1,2,…,71, 2, \dots, 7 in order:

Position ii 11 22 33 44 55 66 77
Column of HH (1,0,0)T(1,0,0)^T (0,1,0)T(0,1,0)^T (1,1,0)T(1,1,0)^T (0,0,1)T(0,0,1)^T (1,0,1)T(1,0,1)^T (0,1,1)T(0,1,1)^T (1,1,1)T(1,1,1)^T
Read bottom to top 001001 010010 011011 100100 101101 110110 111111
In decimal 11 22 33 44 55 66 77

The columns are written bottom-to-top, not top-to-bottom; if you read them the wrong way round every position you report will be the bit-reversal of the truth. A quick way to remember it: the top row is the 11s bit, the middle row is the 22s bit, the bottom row is the 44s bit — the same order as an ordinary binary expansion once you turn your head sideways.

Notice that the columns in positions 1,21, 2 and 44 are exactly the standard basis vectors e1,e2,e3e_1, e_2, e_3. Those are the positions that will hold the check digits, and it is no accident; a check digit whose column is eje_j appears in the jjth equation and no other, so each check digit can be solved for on its own.

Encoding#

Note

Definition (Standard Hamming (7,4)(7,4) Encoding)
Convert the message to binary and break it into chunks of 44 information digits a,b,c,da, b, c, d. Then output the vector

x=(a+b+d, a+c+d, a, b+c+d, b, c, d),x = (a+b+d,\ a+c+d,\ a,\ b+c+d,\ b,\ c,\ d),

where all entries are calculated in Z2\mathbb{Z}_2. This vector contains 33 check digits at positions 1,21, 2 and 44, and has the property that HxT=0Hx^T = 0 over Z2\mathbb{Z}_2.

Basically, the information digits a,b,c,da,b,c,d are dropped into positions 3,5,6,73, 5, 6, 7 untouched, and the three check digits at positions 1,2,41, 2, 4 are each a parity check over a carefully chosen subset of them. The rule is not arbitrary; each check digit exists to make one row of HH sum to zero. Reading the equation HxT=0Hx^T = 0 row by row with x3=ax_3 = a, x5=bx_5 = b, x6=cx_6 = c, x7=dx_7 = d,

row 1:x1+x3+x5+x7=0  ⟹  x1=a+b+d,row 2:x2+x3+x6+x7=0  ⟹  x2=a+c+d,row 3:x4+x5+x6+x7=0  ⟹  x4=b+c+d,\begin{align*} \text{row } 1 &: x_1 + x_3 + x_5 + x_7 = 0 &&\implies x_1 = a + b + d, \\ \text{row } 2 &: x_2 + x_3 + x_6 + x_7 = 0 &&\implies x_2 = a + c + d, \\ \text{row } 3 &: x_4 + x_5 + x_6 + x_7 = 0 &&\implies x_4 = b + c + d, \end{align*}

where we used that −1=1-1 = 1 in Z2\mathbb{Z}_2 so moving a term across the equals sign changes nothing. That derivation is worth internalising, because it is exactly what you repeat when the matrix changes.

Example. Using the standard Hamming (7,4)(7,4) code, encode the message (1,1,0,1)(1,1,0,1).
Here a=1a = 1, b=1b = 1, c=0c = 0, d=1d = 1, so the three check digits are

a+b+d=1+1+1=1,a+c+d=1+0+1=0,b+c+d=1+0+1=0,\begin{align*} a + b + d &= 1 + 1 + 1 \\ &= 1, \\ a + c + d &= 1 + 0 + 1 \\ &= 0, \\ b + c + d &= 1 + 0 + 1 \\ &= 0, \end{align*}

all in Z2\mathbb{Z}_2. Slotting these into positions 1,2,41, 2, 4 and the information digits into positions 3,5,6,73, 5, 6, 7,

x=(1, 0, 1, 0, 1, 0, 1).x = (1,\ 0,\ 1,\ 0,\ 1,\ 0,\ 1).

As a check, HxTHx^T should be the zero vector; row 11 selects positions 1,3,5,71,3,5,7 giving 1+1+1+1=01+1+1+1 = 0, row 22 selects positions 2,3,6,72,3,6,7 giving 0+1+0+1=00+1+0+1 = 0, and row 33 selects positions 4,5,6,74,5,6,7 giving 0+1+0+1=00+1+0+1 = 0. Therefore, the encoded message is (1,0,1,0,1,0,1)(1,0,1,0,1,0,1), and it is a legal codeword.

Example. Using the standard Hamming (7,4)(7,4) code, encode the message (1,0,1,0)(1,0,1,0).
Now a=1a = 1, b=0b = 0, c=1c = 1, d=0d = 0, so

a+b+d=1+0+0=1,a+c+d=1+1+0=0,b+c+d=0+1+0=1,\begin{align*} a + b + d &= 1 + 0 + 0 = 1, \\ a + c + d &= 1 + 1 + 0 = 0, \\ b + c + d &= 0 + 1 + 0 = 1, \end{align*}

in Z2\mathbb{Z}_2. Therefore, the encoded message is (1,0,1,1,0,1,0)(1, 0, 1, 1, 0, 1, 0). Checking against HH once more: positions 1,3,5,71,3,5,7 give 1+1+0+0=01+1+0+0 = 0; positions 2,3,6,72,3,6,7 give 0+1+1+0=00+1+1+0 = 0; positions 4,5,6,74,5,6,7 give 1+0+1+0=01+0+1+0 = 0, so HxT=0Hx^T = 0 as required. Always run this check; it costs three additions and catches every arithmetic slip you could have made in the encoding.

Decoding#

Note

Definition (Standard Hamming (7,4)(7,4) Decoding)
To check for errors (assuming there is at most one) in the received message yy, find z=HyTz = Hy^T. If z=0z = 0, there are no errors. Otherwise, an error exists, and its position is given by the column in HH that matches zz. To read the message, extract the digits of yy in positions 3,5,63, 5, 6 and 77.

Basically, zz is a three-digit binary number that is the position of the broken digit, spelled out bottom-to-top. That is why the columns of HH were arranged in counting order in the first place; the matrix is designed so that the error announces its own address.

Example. Using the standard Hamming (7,4)(7,4) code, decode the received message (1,0,1,1,0,0,1)(1,0,1,1,0,0,1), assuming there is at most one error.
Write y=(1,0,1,1,0,0,1)y = (1,0,1,1,0,0,1) and compute z=HyTz = Hy^T one row at a time, remembering that each row just adds up the entries of yy in the positions where that row of HH has a 11:

z1=y1+y3+y5+y7=1+1+0+1=1,z2=y2+y3+y6+y7=0+1+0+1=0,z3=y4+y5+y6+y7=1+0+0+1=0,\begin{align*} z_1 &= y_1 + y_3 + y_5 + y_7 \\ &= 1 + 1 + 0 + 1 \\ &= 1, \\ z_2 &= y_2 + y_3 + y_6 + y_7 \\ &= 0 + 1 + 0 + 1 \\ &= 0, \\ z_3 &= y_4 + y_5 + y_6 + y_7 \\ &= 1 + 0 + 0 + 1 \\ &= 0, \end{align*}

all in Z2\mathbb{Z}_2, so

z=(100)≠0.z = \begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix} \neq 0.

Since z≠0z \neq 0 there is an error, and z=(1,0,0)Tz = (1,0,0)^T is the first column of HH; equivalently, reading zz from bottom to top gives 001=1001 = 1. So the error is in position 11. Flipping that digit gives the corrected codeword

(0,0,1,1,0,0,1),(0, 0, 1, 1, 0, 0, 1),

and extracting positions 3,5,6,73, 5, 6, 7 gives the message digits (1,0,0,1)(1, 0, 0, 1). Therefore, the decoded message is (1,0,0,1)(1,0,0,1). As a sanity check, encoding (1,0,0,1)(1,0,0,1) gives check digits a+b+d=1+0+1=0a+b+d = 1+0+1 = 0, a+c+d=1+0+1=0a+c+d = 1+0+1 = 0 and b+c+d=0+0+1=1b+c+d = 0+0+1 = 1, i.e. the codeword (0,0,1,1,0,0,1)(0,0,1,1,0,0,1) — exactly the corrected word, so everything is consistent.

Example. Assuming there is at most one error, decode (1,1,0,1,0,1,1)(1,1,0,1,0,1,1) using the standard Hamming (7,4)(7,4) code.
Computing z=HyTz = Hy^T over Z2\mathbb{Z}_2,

z1=y1+y3+y5+y7=1+0+0+1=0,z2=y2+y3+y6+y7=1+0+1+1=1,z3=y4+y5+y6+y7=1+0+1+1=1,\begin{align*} z_1 &= y_1 + y_3 + y_5 + y_7 = 1 + 0 + 0 + 1 = 0, \\ z_2 &= y_2 + y_3 + y_6 + y_7 = 1 + 0 + 1 + 1 = 1, \\ z_3 &= y_4 + y_5 + y_6 + y_7 = 1 + 0 + 1 + 1 = 1, \end{align*}

so z=(0,1,1)Tz = (0,1,1)^T. Reading bottom to top, 110=6110 = 6, and indeed (0,1,1)T(0,1,1)^T is the sixth column of HH; the error is in position 66. Flipping it gives (1,1,0,1,0,0,1)(1,1,0,1,0,0,1), whose digits in positions 3,5,6,73,5,6,7 are (0,0,0,1)(0,0,0,1). Therefore, the decoded message is (0,0,0,1)(0,0,0,1). Checking: encoding (0,0,0,1)(0,0,0,1) gives a+b+d=1a+b+d = 1, a+c+d=1a+c+d = 1, b+c+d=1b+c+d = 1, i.e. (1,1,0,1,0,0,1)(1,1,0,1,0,0,1), which matches.

Example. Assuming there is at most one error, decode (1,0,1,0,1,0,1)(1,0,1,0,1,0,1).
Computing the three parities,

z1=1+1+1+1=0,z2=0+1+0+1=0,z3=0+1+0+1=0,\begin{align*} z_1 &= 1 + 1 + 1 + 1 = 0, \\ z_2 &= 0 + 1 + 0 + 1 = 0, \\ z_3 &= 0 + 1 + 0 + 1 = 0, \end{align*}

so z=0z = 0. Therefore, no error occurred, and the message is read straight off positions 3,5,6,73,5,6,7 as (1,1,0,1)(1,1,0,1) — which is exactly the message we encoded in the first example of this section, as it should be. When z=0z = 0 you do not "correct" anything; you read the message off the received word unchanged.

Non-Standard Hamming Codes#

Why does the decoding rule work at all? The argument is short and it is the most important paragraph in the lecture, because it tells you exactly how much freedom you have in choosing HH.

Suppose a single error occurs at position ii. Over Z2\mathbb{Z}_2, flipping the iith digit is the same as adding 11 to it, so the received word yy is related to the sent word xx by

yT=xT+ei over Z2,y^T = x^T + e_i \text{ over } \mathbb{Z}_2,

where eie_i is the iith standard basis vector. Then, using that matrix multiplication distributes over addition and that HxT=0Hx^T = 0 for every codeword,

HyT=H(xT+ei)=HxT+Hei=0+Hei=Hei,\begin{align*} Hy^T &= H(x^T + e_i) \\ &= Hx^T + He_i \\ &= 0 + He_i \\ &= He_i, \end{align*}

and HeiHe_i is precisely the iith column of HH (multiplying by eie_i picks out column ii and kills everything else). So:

z=HyT is exactly the column of H sitting at the position of the error.\boxed{z = Hy^T \text{ is exactly the column of } H \text{ sitting at the position of the error.}}

Basically, the syndrome zz does not know or care what the message was; it only sees the error. And notice what the argument never used: it never used the fact that the columns of HH were the numbers 11 through 77 in order. All it needs is that the columns are distinct and nonzero, so that "the column matching zz" picks out a unique position.

This tells us that the decoding method will work regardless of the matrix HH used, implying that variations of the standard Hamming (7,4)(7,4) code exist where a different matrix H′H' uses some permutation of the original columns. With such an H′H' we still calculate z=H′yTz = H'y^T, and (assuming at most one error) if z=0z = 0 then there are no errors, while otherwise there is one error at the position corresponding with the column in H′H' that matches zz.

The error-checking method is unchanged, but the encoding rule certainly is not. The check digits are always determined by insisting that H′xT=0H'x^T = 0, and you have to redo the row-by-row solve to find out what they are. The other feature that may change is where the check and information digits sit: typically the check digits are placed so that their corresponding columns in H′H' are the standard basis vectors eie_i, because then each check digit appears in exactly one of the three equations and can be read off immediately. If you put a check digit somewhere else, the three equations tangle together and you have to solve a genuine simultaneous system.

Example. Consider the non-standard Hamming matrix

H′=(100111001011010011011).H' = \begin{pmatrix} 1 & 0 & 0 & 1 & 1 & 1 & 0 \\ 0 & 1 & 0 & 1 & 1 & 0 & 1 \\ 0 & 0 & 1 & 1 & 0 & 1 & 1 \end{pmatrix}.

Supposing that the information digits are in the last four positions, decode the received message y=(1,0,1,1,1,0,1)y = (1,0,1,1,1,0,1), assuming at most one error.
First read off which positions each row of H′H' selects: row 11 has 11s in positions 1,4,5,61,4,5,6; row 22 in positions 2,4,5,72,4,5,7; row 33 in positions 3,4,6,73,4,6,7. Computing z=H′yTz = H'y^T over Z2\mathbb{Z}_2,

z1=y1+y4+y5+y6=1+1+1+0=1,z2=y2+y4+y5+y7=0+1+1+1=1,z3=y3+y4+y6+y7=1+1+0+1=1,\begin{align*} z_1 &= y_1 + y_4 + y_5 + y_6 \\ &= 1 + 1 + 1 + 0 \\ &= 1, \\ z_2 &= y_2 + y_4 + y_5 + y_7 \\ &= 0 + 1 + 1 + 1 \\ &= 1, \\ z_3 &= y_3 + y_4 + y_6 + y_7 \\ &= 1 + 1 + 0 + 1 \\ &= 1, \end{align*}

so z=(1,1,1)T≠0z = (1,1,1)^T \neq 0 and an error has occurred. Now hunt for the column of H′H' equal to (1,1,1)T(1,1,1)^T; scanning across, the only all-ones column is the fourth. Do not convert zz to a number here — with a non-standard matrix the columns are not in counting order, so position 44 has nothing to do with zz "being" 77 in binary; you must physically match the column. Flipping digit 44 of yy gives the corrected codeword

(1,0,1,0,1,0,1),(1, 0, 1, 0, 1, 0, 1),

and since the information digits live in the last four positions, the message is (0,1,0,1)(0, 1, 0, 1). Therefore, the decoded message is (0,1,0,1)(0,1,0,1).

Example. Find the encoding rule for the previous Hamming code, using the same non-standard Hamming matrix H′H', where the information digits are placed in the last four positions.
Write the codeword as x=(x1,x2,x3,a,b,c,d)x = (x_1, x_2, x_3, a, b, c, d), so that x1,x2,x3x_1, x_2, x_3 are the check digits and a,b,c,da,b,c,d are the information digits. Notice first that the columns in positions 1,2,31, 2, 3 of H′H' are e1,e2,e3e_1, e_2, e_3, so each check digit appears in exactly one equation; this is the situation we wanted. Now impose H′xT=0H'x^T = 0 row by row:

row 1:x1+a+b+c=0  ⟹  x1=a+b+c,row 2:x2+a+b+d=0  ⟹  x2=a+b+d,row 3:x3+a+c+d=0  ⟹  x3=a+c+d,\begin{align*} \text{row } 1 &: x_1 + a + b + c = 0 &&\implies x_1 = a + b + c, \\ \text{row } 2 &: x_2 + a + b + d = 0 &&\implies x_2 = a + b + d, \\ \text{row } 3 &: x_3 + a + c + d = 0 &&\implies x_3 = a + c + d, \end{align*}

where again we used −1=1-1 = 1 in Z2\mathbb{Z}_2, so rearranging never introduces a minus sign. Therefore, the encoding rule is

x=(a+b+c, a+b+d, a+c+d, a, b, c, d),x = (a+b+c,\ a+b+d,\ a+c+d,\ a,\ b,\ c,\ d),

with all entries computed in Z2\mathbb{Z}_2.

As a sanity check, run the message (a,b,c,d)=(0,1,0,1)(a,b,c,d) = (0,1,0,1) recovered in the previous example through this rule:

a+b+c=0+1+0=1,a+b+d=0+1+1=0,a+c+d=0+0+1=1,\begin{align*} a + b + c &= 0 + 1 + 0 = 1, \\ a + b + d &= 0 + 1 + 1 = 0, \\ a + c + d &= 0 + 0 + 1 = 1, \end{align*}

giving x=(1,0,1,0,1,0,1)x = (1,0,1,0,1,0,1), which is exactly the corrected codeword we obtained. Two independent calculations agreeing like this is the best evidence you will get in an exam that both of them are right.

Example. Consider the non-standard Hamming matrix

H′′=(111010001110101101001)H'' = \begin{pmatrix} 1 & 1 & 1 & 0 & 1 & 0 & 0 \\ 0 & 1 & 1 & 1 & 0 & 1 & 0 \\ 1 & 1 & 0 & 1 & 0 & 0 & 1 \end{pmatrix}

over Z2\mathbb{Z}_2, where the last three entries of an encoded message are the check digits.
(a) Find the encoding rule.
(b) Assuming there is at most one error, decode the message (0,0,0,1,1,1,0)(0,0,0,1,1,1,0).

(a) The columns in positions 5,6,75, 6, 7 are e1,e2,e3e_1, e_2, e_3, which is consistent with the check digits being placed there. Write x=(a,b,c,d,x5,x6,x7)x = (a,b,c,d,x_5,x_6,x_7). Row 11 has 11s in positions 1,2,3,51,2,3,5; row 22 in positions 2,3,4,62,3,4,6; row 33 in positions 1,2,4,71,2,4,7. Imposing H′′xT=0H''x^T = 0,

row 1:a+b+c+x5=0  ⟹  x5=a+b+c,row 2:b+c+d+x6=0  ⟹  x6=b+c+d,row 3:a+b+d+x7=0  ⟹  x7=a+b+d.\begin{align*} \text{row } 1 &: a + b + c + x_5 = 0 &&\implies x_5 = a + b + c, \\ \text{row } 2 &: b + c + d + x_6 = 0 &&\implies x_6 = b + c + d, \\ \text{row } 3 &: a + b + d + x_7 = 0 &&\implies x_7 = a + b + d. \end{align*}

Therefore, the encoding rule is x=(a, b, c, d, a+b+c, b+c+d, a+b+d)x = (a,\ b,\ c,\ d,\ a+b+c,\ b+c+d,\ a+b+d).

(b) With y=(0,0,0,1,1,1,0)y = (0,0,0,1,1,1,0), computing z=H′′yTz = H''y^T over Z2\mathbb{Z}_2,

z1=y1+y2+y3+y5=0+0+0+1=1,z2=y2+y3+y4+y6=0+0+1+1=0,z3=y1+y2+y4+y7=0+0+1+0=1,\begin{align*} z_1 &= y_1 + y_2 + y_3 + y_5 \\ &= 0 + 0 + 0 + 1 \\ &= 1, \\ z_2 &= y_2 + y_3 + y_4 + y_6 \\ &= 0 + 0 + 1 + 1 \\ &= 0, \\ z_3 &= y_1 + y_2 + y_4 + y_7 \\ &= 0 + 0 + 1 + 0 \\ &= 1, \end{align*}

so z=(1,0,1)Tz = (1,0,1)^T, which matches the first column of H′′H''. Flipping digit 11 gives the corrected codeword (1,0,0,1,1,1,0)(1,0,0,1,1,1,0), and the information digits are the first four, namely (1,0,0,1)(1,0,0,1). Therefore, the decoded message is (1,0,0,1)(1,0,0,1). Checking against part (a) with a=1,b=0,c=0,d=1a=1, b=0, c=0, d=1: x5=1+0+0=1x_5 = 1+0+0 = 1, x6=0+0+1=1x_6 = 0+0+1 = 1, x7=1+0+1=0x_7 = 1+0+1 = 0, giving (1,0,0,1,1,1,0)(1,0,0,1,1,1,0) as required.

Notice how in both non-standard examples the answer came out of the same three-step routine, and the matrix never had to be memorised:

  • Identify which positions hold check digits (look for the columns that are e1,e2,e3e_1, e_2, e_3).
  • For the encoding rule, read each row of H′H' as "the sum of the digits in these positions is 00", and solve each row for its check digit.
  • For decoding, compute z=H′yTz = H'y^T by the same row-selects-positions rule, then match zz against the columns of H′H' by eye.

Larger Hamming Codes#

The Hamming (7,4)(7,4) code is so-called because it encodes messages of length 44 as messages of length 77; that is, it introduces 33 check digits. Hamming codes of other sizes are designed in exactly the same fashion, and the pattern is driven entirely by the columns.

With rr rows, the columns of HH can be any nonzero binary strings of length rr, and there are 2r−12^r - 1 of those; so the longest codeword we can protect with rr check digits has 2r−12^r - 1 digits, of which 2r−1−r2^r - 1 - r carry information. This gives the family

Hamming (2r−1, 2r−1−r) for r=2,3,4,…\boxed{\text{Hamming } (2^r - 1,\ 2^r - 1 - r) \text{ for } r = 2, 3, 4, \dots}

so r=3r = 3 gives (7,4)(7,4), r=4r = 4 gives (15,11)(15,11), r=5r = 5 gives (31,26)(31, 26), and so on. Notice what happens to the rate: 47≈0.57\tfrac47 \approx 0.57, then 1115≈0.73\tfrac{11}{15} \approx 0.73, then 2631≈0.84\tfrac{26}{31} \approx 0.84. Bigger Hamming codes are much more efficient, but they still only correct one error per block; a long block is a bigger target, so the single-error assumption gets harder to justify as rr grows. That trade-off is the whole design problem.

The next one up uses the standard Hamming (15,11)(15,11) matrix

H=(101010101010101011001100110011000111100001111000000011111111),H = \begin{pmatrix} 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 & 0 & 1 \\ 0 & 1 & 1 & 0 & 0 & 1 & 1 & 0 & 0 & 1 & 1 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 1 & 1 & 1 & 1 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \end{pmatrix},

whose columns are the integers 11 through to 1515 in binary, reading from bottom to top. The rows are exactly the 11s bit, the 22s bit, the 44s bit and the 88s bit of the column number, which is why each row looks like a doubling of the pattern above it: alternate singles, then pairs, then fours, then eights.

Note

Definition (Standard Hamming (15,11)(15,11) Code)
Encoding. Convert the message to binary and break it into chunks of 1111 information digits a1,a2,…,a11a_1, a_2, \dots, a_{11}. Then to ensure HxT=0Hx^T = 0, output the vector

x=(c1, c2, a1, c3, a2, a3, a4, c4, a5, a6, a7, a8, a9, a10, a11),x = (c_1,\ c_2,\ a_1,\ c_3,\ a_2,\ a_3,\ a_4,\ c_4,\ a_5,\ a_6,\ a_7,\ a_8,\ a_9,\ a_{10},\ a_{11}),

where, in Z2\mathbb{Z}_2,

c1=a1+a2+a4+a5+a7+a9+a11,c2=a1+a3+a4+a6+a7+a10+a11,c3=a2+a3+a4+a8+a9+a10+a11,c4=a5+a6+a7+a8+a9+a10+a11.\begin{align*} c_1 &= a_1 + a_2 + a_4 + a_5 + a_7 + a_9 + a_{11}, \\ c_2 &= a_1 + a_3 + a_4 + a_6 + a_7 + a_{10} + a_{11}, \\ c_3 &= a_2 + a_3 + a_4 + a_8 + a_9 + a_{10} + a_{11}, \\ c_4 &= a_5 + a_6 + a_7 + a_8 + a_9 + a_{10} + a_{11}. \end{align*}

Decoding. As before, if HyTHy^T is the iith column of HH, correct the iith digit of yy.

You do not have to memorise those four formulas, and you should not try; they are just the same row-by-row solve applied to a bigger matrix. The check digits sit at positions 1,2,4,81, 2, 4, 8 (the powers of 22, which are exactly the positions where the column of HH is a standard basis vector), and cjc_j is the sum of every information digit whose position has a 11 in the jjth bit. For instance row 11 of HH has 11s at the odd positions 1,3,5,7,9,11,13,151,3,5,7,9,11,13,15, and dropping x1=c1x_1 = c_1 out of that list leaves positions 3,5,6,…3,5,6,\dots holding a1,a2,a4,a5,a7,a9,a11a_1, a_2, a_4, a_5, a_7, a_9, a_{11} — which is precisely the formula for c1c_1.

Example. Using the standard Hamming (15,11)(15,11) code, encode the message (1,0,1,0,1,0,1,0,1,0,1)(1,0,1,0,1,0,1,0,1,0,1).
Here a1=1,a2=0,a3=1,a4=0,a5=1,a6=0,a7=1,a8=0,a9=1,a10=0,a11=1a_1 = 1, a_2 = 0, a_3 = 1, a_4 = 0, a_5 = 1, a_6 = 0, a_7 = 1, a_8 = 0, a_9 = 1, a_{10} = 0, a_{11} = 1. Computing the four check digits in Z2\mathbb{Z}_2,

c1=a1+a2+a4+a5+a7+a9+a11=1+0+0+1+1+1+1=1,c2=a1+a3+a4+a6+a7+a10+a11=1+1+0+0+1+0+1=0,c3=a2+a3+a4+a8+a9+a10+a11=0+1+0+0+1+0+1=1,c4=a5+a6+a7+a8+a9+a10+a11=1+0+1+0+1+0+1=0.\begin{align*} c_1 &= a_1 + a_2 + a_4 + a_5 + a_7 + a_9 + a_{11} \\ &= 1 + 0 + 0 + 1 + 1 + 1 + 1 \\ &= 1, \\ c_2 &= a_1 + a_3 + a_4 + a_6 + a_7 + a_{10} + a_{11} \\ &= 1 + 1 + 0 + 0 + 1 + 0 + 1 \\ &= 0, \\ c_3 &= a_2 + a_3 + a_4 + a_8 + a_9 + a_{10} + a_{11} \\ &= 0 + 1 + 0 + 0 + 1 + 0 + 1 \\ &= 1, \\ c_4 &= a_5 + a_6 + a_7 + a_8 + a_9 + a_{10} + a_{11} \\ &= 1 + 0 + 1 + 0 + 1 + 0 + 1 \\ &= 0. \end{align*}

Slotting the check digits into positions 1,2,4,81, 2, 4, 8 and the information digits into the rest,

x=(1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1).x = (1,\ 0,\ 1,\ 1,\ 0,\ 1,\ 0,\ 0,\ 1,\ 0,\ 1,\ 0,\ 1,\ 0,\ 1).

Therefore, the encoded message is (1,0,1,1,0,1,0,0,1,0,1,0,1,0,1)(1,0,1,1,0,1,0,0,1,0,1,0,1,0,1). (Counting 11s in the odd positions gives 1+1+0+0+1+1+1+1=61+1+0+0+1+1+1+1 = 6, which is even, so row 11 of HH checks out; the other three rows check the same way.)

Example. Assuming there is at most one error, decode (1,1,0,1,1,0,1,1,0,1,1,0,1,1,0)(1,1,0,1,1,0,1,1,0,1,1,0,1,1,0) using the standard Hamming (15,11)(15,11) code.
Each row of HH selects the positions where that row has a 11, so

z1=y1+y3+y5+y7+y9+y11+y13+y15=1+0+1+1+0+1+1+0=1,z2=y2+y3+y6+y7+y10+y11+y14+y15=1+0+0+1+1+1+1+0=1,z3=y4+y5+y6+y7+y12+y13+y14+y15=1+1+0+1+0+1+1+0=1,z4=y8+y9+y10+y11+y12+y13+y14+y15=1+0+1+1+0+1+1+0=1,\begin{align*} z_1 &= y_1 + y_3 + y_5 + y_7 + y_9 + y_{11} + y_{13} + y_{15} \\ &= 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 \\ &= 1, \\ z_2 &= y_2 + y_3 + y_6 + y_7 + y_{10} + y_{11} + y_{14} + y_{15} \\ &= 1 + 0 + 0 + 1 + 1 + 1 + 1 + 0 \\ &= 1, \\ z_3 &= y_4 + y_5 + y_6 + y_7 + y_{12} + y_{13} + y_{14} + y_{15} \\ &= 1 + 1 + 0 + 1 + 0 + 1 + 1 + 0 \\ &= 1, \\ z_4 &= y_8 + y_9 + y_{10} + y_{11} + y_{12} + y_{13} + y_{14} + y_{15} \\ &= 1 + 0 + 1 + 1 + 0 + 1 + 1 + 0 \\ &= 1, \end{align*}

all in Z2\mathbb{Z}_2, so z=(1,1,1,1)Tz = (1,1,1,1)^T. Reading bottom to top gives 1111=151111 = 15, so the error is in position 1515. Flipping that digit gives the corrected codeword

(1,1,0,1,1,0,1,1,0,1,1,0,1,1,1),(1,1,0,1,1,0,1,1,0,1,1,0,1,1,1),

and deleting the check digits at positions 1,2,4,81, 2, 4, 8 leaves the information digits at positions 3,5,6,7,9,10,…,153,5,6,7,9,10,\dots,15:

(0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1).(0,\ 1,\ 0,\ 1,\ 0,\ 1,\ 1,\ 0,\ 1,\ 1,\ 1).

Therefore, the decoded message is (0,1,0,1,0,1,1,0,1,1,1)(0,1,0,1,0,1,1,0,1,1,1). (Recomputing zz on the corrected word gives (0,0,0,0)T(0,0,0,0)^T, confirming that it is now a legal codeword.)

Codes that can correct multiple errors do exist, but they need more machinery than we have; that idea gets picked up again in Topic 9.

What Hamming Codes Can and Cannot Do#

It is worth being very precise about the guarantee, because the phrasing "assuming there is at most one error" is doing enormous work.

If exactly one error occurs, the code always corrects it: we proved above that z=Heiz = He_i is column ii, the columns are distinct, so the position is pinned down uniquely and flipping it restores the sent word. If no error occurs, z=0z = 0 and nothing is touched. So far so good.

Now suppose two errors occur, at positions ii and jj. The same computation gives

HyT=H(xT+ei+ej)=0+Hei+Hej=(column i)+(column j),\begin{align*} Hy^T &= H(x^T + e_i + e_j) \\ &= 0 + He_i + He_j \\ &= (\text{column } i) + (\text{column } j), \end{align*}

which is nonzero (the columns are distinct, so their Z2\mathbb{Z}_2 sum cannot be zero). The receiver therefore does see that something is wrong — but the sum of two columns is itself a column, so the decoder happily concludes "one error, at position kk", flips a third perfectly good digit, and hands over a legal-looking codeword that is not the one you sent.

Example. The codeword x=(1,0,1,0,1,0,1)x = (1,0,1,0,1,0,1) (the encoding of (1,1,0,1)(1,1,0,1)) is sent and the first two digits are flipped, so y=(0,1,1,0,1,0,1)y = (0,1,1,0,1,0,1) arrives. What does the standard decoder report?
Computing z=HyTz = Hy^T,

z1=y1+y3+y5+y7=0+1+1+1=1,z2=y2+y3+y6+y7=1+1+0+1=1,z3=y4+y5+y6+y7=0+1+0+1=0,\begin{align*} z_1 &= y_1 + y_3 + y_5 + y_7 = 0 + 1 + 1 + 1 = 1, \\ z_2 &= y_2 + y_3 + y_6 + y_7 = 1 + 1 + 0 + 1 = 1, \\ z_3 &= y_4 + y_5 + y_6 + y_7 = 0 + 1 + 0 + 1 = 0, \end{align*}

so z=(1,1,0)Tz = (1,1,0)^T, which is column 33 of HH (bottom to top, 011=3011 = 3). The decoder therefore "corrects" position 33, producing (0,1,0,0,1,0,1)(0,1,0,0,1,0,1), and reads the message off positions 3,5,6,73,5,6,7 as (0,1,0,1)(0,1,0,1). Therefore, the decoder confidently returns (0,1,0,1)(0,1,0,1) when the true message was (1,1,0,1)(1,1,0,1); it has flagged an error, mis-located it, and made the word more wrong. The plain Hamming (7,4)(7,4) code corrects one error, but it does not reliably detect two; with two errors it will silently mis-correct into a different valid codeword. (Real systems fix this by appending one extra overall parity digit, giving a code that corrects one error and detects two — but that is not the code you are given here, so do not claim double-error detection in an exam.)

The standard traps, collected in one place:

  • Reading the columns of HH top-to-bottom instead of bottom-to-top. Position 33 has column (1,1,0)T(1,1,0)^T, not (0,1,1)T(0,1,1)^T; getting this backwards swaps positions 3↔63 \leftrightarrow 6 and 1↔41 \leftrightarrow 4 and gives a wrong answer that still "looks" plausible.
  • Converting zz to a decimal number when the matrix is non-standard. The "read zz as a binary number" shortcut is a coincidence of the standard matrix having its columns in counting order; for any H′H' you must match zz against the columns physically.
  • Forgetting to correct before extracting. The message digits come from the corrected word, not the received one. If z≠0z \neq 0 and the flagged position happens to be an information digit, extracting from yy directly gives the wrong message.
  • Forgetting where the information digits live. For the standard (7,4)(7,4) code they are at positions 3,5,6,73,5,6,7; for a non-standard code they can be anywhere, and the question will tell you. Read that sentence twice.
  • Doing the arithmetic over Z\mathbb{Z} instead of Z2\mathbb{Z}_2. A check digit is never 22 or 33; reduce mod 22 at every step (see Modular Rings and Units if you want the general story).
  • Quoting the encoding rule of the standard code for a non-standard matrix. The decoding method is matrix-independent by the HeiHe_i argument; the encoding rule is not, and must be re-derived from H′xT=0H'x^T = 0 every single time.

Stepping back, the whole lecture is one idea repeated at increasing levels of cleverness. A parity check imposes one linear equation on the transmitted digits and buys you detection of an odd number of errors for one extra digit. Reduplication imposes many equations and buys correction, but at a rate of 12\tfrac12 or 13\tfrac13. Hamming codes impose rr carefully chosen equations — one per row of HH — and arrange the columns so that the failed equations spell out the address of the broken digit in binary; that gets you single-error correction at a rate of 2r−1−r2r−1\tfrac{2^r-1-r}{2^r-1}, which tends to 11 as rr grows. Redundancy is the price of reliability, and Hamming's contribution was working out how little of it you actually have to pay.