Markov chain Monte Carlo (MCMC) is a technique for estimating by simulation the expectation of a statistic in a complex model. Successive random selections form a Markov chain, the stationary distribution of which is the target distribution. It is particularly useful for the evaluation of posterior distributions in complex Bayesian models. In the Metropolis–Hastings algorithm, items are selected from an arbitrary “proposal” distribution and are retained or not according to an acceptance rule. The Gibbs sampler is a special case in which the proposal distributions are conditional distributions of single components of a vector parameter. Various special cases and applications are considered.

I can only vaguely understand what the author is saying here (and really only because I know ahead of time what MCMC is). There are certainly references to more advanced things than what I’m going to cover in this post. But it seems very difficult to find an explanation of Markov Chain Monte Carlo *without *all any superfluous jargon. The “bullshit” here is the implicit claim of an author that such jargon is needed. Maybe it is to explain advanced applications (like attempts to do “inference in Bayesian networks”), but it is certainly not needed to define or analyze the basic ideas.

So to counter, here’s my own explanation of Markov Chain Monte Carlo, inspired by the treatment of John Hopcroft and Ravi Kannan.

Markov Chain Monte Carlo is a technique to solve the problem of *sampling from a complicated distribution. *Let me explain by the following imaginary scenario. Say I have a magic box which can estimate probabilities of baby names very well. I can give it a string like “Malcolm” and it will tell me the exact probability that you will choose this name for your next child. So there’s a distribution over all names, it’s very specific to your preferences, and for the sake of argument say this distribution is fixed and you don’t get to tamper with it.

Now comes the problem: I want to *efficiently draw* a name from this distribution . This is the problem that Markov Chain Monte Carlo aims to solve. Why is it a problem? Because I have no idea what process you use to pick a name, so I can’t simulate that process myself. Here’s another method you could try: generate a name uniformly at random, ask the machine for , and then flip a biased coin with probability and use if the coin lands heads. The problem with this is that there are exponentially many names! The variable here is the number of bits needed to write down a name . So either the probabilities will be exponentially small and I’ll be flipping for a very long time to get a single name, or else there will only be a few names with nonzero probability and it will take me exponentially many draws to find them. Inefficiency is the death of me.

So this is a serious problem! Let’s restate it formally just to be clear.

**Definition (The sampling problem): ** Let be a distribution over a finite set . You are given black-box access to the probability distribution function which outputs the probability of drawing according to . Design an efficient randomized algorithm which outputs an element of so that the probability of outputting is approximately . More generally, output a sample of elements from drawn according to .

Assume that has access to only fair random coins, though this allows one to efficiently simulate flipping a biased coin of any desired probability.

Notice that with such an algorithm we’d be able to do things like estimate the expected value of some random variable . We could take a large sample via the solution to the sampling problem, and then compute the average value of on that sample. This is what a Monte Carlo method does when sampling is easy. In fact, the Markov Chain solution to the sampling problem will allow us to do the sampling *and* the estimation of in one fell swoop if you want.

But the core problem is really a sampling problem, and “Markov Chain Monte Carlo” would be more accurately called the “Markov Chain Sampling Method.” So let’s see why a Markov Chain could possibly help us.

Markov Chain is essentially a fancy term for a random walk on a graph.

You give me a directed graph , and for each edge you give me a number . In order to make a random walk make sense, the need to satisfy the following constraint:

For any vertex , the set all values on outgoing edges must sum to 1, i.e. form a probability distribution.

If this is satisfied then we can take a random walk on according to the probabilities as follows: start at some vertex . Then pick an outgoing edge at random according to the probabilities on the outgoing edges, and follow it to . Repeat if possible.

I say “if possible” because an arbitrary graph will not necessarily have any outgoing edges from a given vertex. We’ll need to impose some additional conditions on the graph in order to apply random walks to Markov Chain Monte Carlo, but in any case the idea of randomly walking is well-defined, and we call the whole object a *Markov chain.*

Here is an example where the vertices in the graph correspond to emotional states.

In statistics land, they take the “state” interpretation of a random walk very seriously. They call the edge probabilities “state-to-state transitions.”The main theorem we need to do anything useful with Markov chains is the stationary distribution theorem (sometimes called the “Fundamental Theorem of Markov Chains,” and for good reason). What it says intuitively is that for a very long random walk, the probability that you end at some vertex is independent of where you started! All of these probabilities taken together is called the *stationary distribution *of the random walk, and it is uniquely determined by the Markov chain.

However, for the reasons we stated above (“if possible”), the stationary distribution theorem is not true of every Markov chain. The main property we need is that the graph is *strongly connected.* Recall that a directed graph is called connected if, when you ignore direction, there is a path from every vertex to every other vertex. It is called *strongly connected* if you still get paths everywhere when considering direction. If we additionally require the stupid edge-case-catcher that no edge can have zero probability, then strong connectivity (of one component of a graph) is equivalent to the following property:

For every vertex , an infinite random walk started at will return to with probability 1.

In fact it will return infinitely often. This property is called the *persistence *of the state by statisticians. I dislike this term because it appears to describe a property of a vertex, when to me it describes a property of the connected component containing that vertex. In any case, since in Markov Chain Monte Carlo we’ll be picking the graph to walk on (spoiler!) we will ensure the graph is strongly connected by design.

Finally, in order to describe the stationary distribution in a more familiar manner (using linear algebra), we will write the transition probabilities as a matrix where entry if there is an edge and zero otherwise. Here the rows and columns correspond to vertices of , and each *column* forms the probability distribution of going from state to some other state in one step of the random walk. Note is the transpose of the weighted adjacency matrix of the directed weighted graph where the weights are the transition probabilities (the reason I do it this way is because matrix-vector multiplication will have the matrix on the left instead of the right; see below).

This matrix allows me to describe things nicely using the language of linear algebra. In particular if you give me a basis vector interpreted as “the random walk currently at vertex ,” then gives a vector whose -th coordinate is the probability that the random walk would be at vertex after one more step in the random walk. Likewise, if you give me a probability distribution over the vertices, then gives a probability vector interpreted as follows:

If a random walk is in state with probability , then the -th entry of is the probability that after one more step in the random walk you get to vertex .

Interpreted this way, the stationary distribution is a probability distribution such that , in other words is an eigenvector of with eigenvalue 1.

A quick side note for avid readers of this blog: this analysis of a random walk is exactly what we did back in the early days of this blog when we studied the PageRank algorithm for ranking webpages. There we called the matrix “a web matrix,” noted it was column stochastic (as it is here), and appealed to a special case of the Perron-Frobenius theorem to show that there is a unique maximal eigenvalue equal to one (with a dimension one eigenspace) whose eigenvector we used as a sort of “stationary distribution” and the final ranking of web pages. There we described an algorithm to actually find that eigenvector by iterated multiplication by . The following theorem is essentially a variant of this algorithm but works under weaker conditions; for the web matrix we added additional “fake” edges that give the needed stronger conditions.

**Theorem: **Let be a strongly connected graph with associated edge probabilities forming a Markov chain. For a probability vector , define for all , and let be the long-term average . Then:

- There is a unique probability vector with .
- For all , the limit .

*Proof. *Since is a probability vector we just want to show that as . Indeed, we can expand this quantity as

But are unit vectors, so their difference is at most 2, meaning . Now it’s clear that this does not depend on . For uniqueness we will cop out and appeal to the Perron-Frobenius theorem that says any matrix of this form has a unique such (normalized) eigenvector.

One additional remark is that, in addition to computing the stationary distribution by actually computing this average or using an eigensolver, one can analytically solve for it as the inverse of a particular matrix. Define , where is the identity matrix. Let be with a row of ones appended to the bottom and the topmost row removed. Then one can show (quite opaquely) that the last column of is . We leave this as an exercise to the reader, because I’m pretty sure nobody uses this method in practice.

One final remark is about why we need to take an average over all our in the theorem above. There is an extra technical condition one can add to strong connectivity, called *aperiodicity*, which allows one to beef up the theorem so that itself converges to the stationary distribution. Rigorously, aperiodicity is the property that, regardless of where you start your random walk, after some sufficiently large number of steps the random walk has a positive probability of being at every vertex at every subsequent step. As an example of a graph where aperiodicity fails: an undirected cycle on an even number of vertices. In that case there will only be a positive probability of being at certain vertices every *other* step, and averaging those two long term sequences gives the actual stationary distribution.

One way to guarantee that your Markov chain is aperiodic is to ensure there is a positive probability of staying at any vertex. I.e., that your graph has a self-loop. This is what we’ll do in the next section.

Recall that the problem we’re trying to solve is to draw from a distribution over a finite set with probability function . The MCMC method is to construct a Markov chain whose stationary distribution is exactly , even when you just have black-box access to evaluating . That is, you (implicitly) pick a graph and (implicitly) choose transition probabilities for the edges to make the stationary distribution . Then you take a long enough random walk on and output the corresponding to whatever state you land on.

The easy part is coming up with a graph that has the right stationary distribution (in fact, “most” graphs will work). The hard part is to come up with a graph where you can prove that the convergence of a random walk to the stationary distribution is fast in comparison to the size of . Such a proof is beyond the scope of this post, but the “right” choice of a graph is not hard to understand.

The one we’ll pick for this post is called the **Metropolis-Hastings** algorithm. The input is your black-box access to , and the output is a set of rules that implicitly define a random walk on a graph whose vertex set is .

It works as follows: you pick some way to put on a lattice, so that each state corresponds to some vector in . Then you add (two-way directed) edges to all neighboring lattice points. For it would look like this:

And for it would look like this:

You have to be careful here to ensure the vertices you choose for are not disconnected, but in many applications is naturally already a lattice.

Now we have to describe the transition probabilities. Let be the maximum degree of a vertex in this lattice (). Suppose we’re at vertex and we want to know where to go next. We do the following:

- Pick neighbor with probability (there is some chance to stay at ).
- If you picked neighbor and then deterministically go to .
- Otherwise, , and you go to with probability .

We can state the probability weight on edge more compactly as

It is easy to check that this is indeed a probability distribution for each vertex . So we just have to show that is the stationary distribution for this random walk.

Here’s a fact to do that: if a probability distribution with entries for each has the property that for all , the is the stationary distribution. To prove it, fix and take the sum of both sides of that equation over all . The result is exactly the equation , which is the same as . Since the stationary distribution is the unique vector satisfying this equation, has to be it.

Doing this with out chosen is easy, since and are both equal to by applying a tiny bit of algebra to the definition. So we’re done! One can just randomly walk according to these probabilities and get a sample.

The last thing I want to say about MCMC is to show that you can estimate the expected value of a function simultaneously while random-walking through your Metropolis-Hastings graph (or any graph whose stationary distribution is ). By definition the expected value of is .

Now what we can do is compute the average value of just among those states we’ve visited during our random walk. With a little bit of extra work you can show that this quantity will converge to the true expected value of at about the same time that the random walk converges to the stationary distribution. (Here the “about” means we’re off by a constant factor depending on ). In order to prove this you need some extra tools I’m too lazy to write about in this post, but the point is that it works.

The reason I did not start by describing MCMC in terms of estimating the expected value of a function is because the core problem is a sampling problem. Moreover, there are many applications of MCMC that need nothing more than a sample. For example, MCMC can be used to estimate the volume of an arbitrary (maybe high dimensional) convex set. See these lecture notes of Alistair Sinclair for more.

If demand is popular enough, I could implement the Metropolis-Hastings algorithm in code (it wouldn’t be industry-strength, but perhaps illuminating? I’m not so sure…).

Until next time!

]]>

Recall that a code is a set of strings called *codewords*, and that the parameters of a code are written . Remember is the length of a codeword, is the message length, is the minimum distance between any two codewords, and is the size of the alphabet used for the codewords. Finally, remember that for linear codes our alphabets were either just where , or more generally a finite field for a prime power.

One way to motivate for the Singleton bound goes like this. We can easily come up with codes for the following parameters. For the identity function works. And to get a -code we can encode a binary string by appending the parity bit to the end (as an easy exercise, verify this has distance 2). An obvious question is can we generalize this to a -code for any ? Perhaps a more obvious question is: why can’t we hope for better? A larger or ? Because the Singleton bound says so.

**Theorem [Singleton 64]:** If is an -code, then .

*Proof.* The proof is pleasantly simple. Let be your alphabet and look at the projection map which projects . Remember that the size of the code is , and because the codomain of i.e. has size , it follows that is not an injective map. In particular, there are two codewords whose first coordinates are equal. Even if all of their remaining coordinates differ, this implies that .

It’s embarrassing that such a simple argument can prove that one can do no better. There are codes that meet this bound and they are called *maximum distance separable* (MDS) codes. One might wonder how MDS codes relate to perfect codes, but they are incomparable; there are perfect codes that are not MDS codes, and conversely MDS codes need not be perfect. The Reed-Solomon code is an example of the latter.

The Reed-Solomon code has a very simple definition, especially for those of you who have read about secret sharing.

Given a prime power and integers , the *Reed-Solomon* code with these parameters is defined by its encoding function as follows.

- Generate explicitly.
- Pick distinct elements .
- A message is a list of elements . Represent the message as a polynomial .
- The encoding of a message is the tuple . That is, we just evaluate at our chosen locations in .

Here’s an example when . We’ll pick the points , and let our message be , which is encoded as a polynomial . Then the encoding of the message is

Decoding the message is a bit more difficult (more on that next time), but for now let’s prove the basic facts about this code.

**Fact:** The Reed-Solomon code is linear. This is just because polynomials of a limited degree form a vector space. Adding polynomials is adding their coefficients, and scaling them is scaling their coefficients. Moreover, the *evaluation* of a polynomial at a point is a linear map, i.e. it’s always true that , and scaling the coefficients is no different. So the codewords also form a vector space.

**Fact: **, or equivalently the Reed-Solomon code meets the Singleton bound. This follows from a simple fact: any two *different* single-variable polynomials of degree at most agree on at most points. Indeed, otherwise two such polynomials would give a new polynomial which has more than roots, but the fundamental theorem of algebra (the adaptation for finite fields) says the only polynomial with this many roots is the zero polynomial.

So the Reed-Solomon code is maximum distance separable. Neat!

One might wonder why one would want good codes with large alphabets. One reason is that with a large alphabet we can interpret a byte as an element of to get error correction on bytes. So if you want to encode some really large stream of bytes (like a DVD) using such a scheme and you get bursts of contiguous errors in small regions (like a scratch), then you can do pretty powerful error correction. In fact, this is more or less the idea behind error correction for DVDs. So I hear. You can read more about the famous applications at Wikipedia.

The Reed-Muller code is a neat generalization of the Reed-Solomon code to multivariable polynomials. The reason they’re so useful is not necessarily because they optimize some bound (if they do, I haven’t heard of it), but because they specialize to all sorts of useful codes with useful properties. One of these is properties is called *local decodability*, which has big applications in theoretical computer science.

Anyway, before I state the definition let me remind the reader about compact notation for multivariable polynomials. I can represent the variables used in the polynomial as a vector and likewise a monomial by a “vector power” , where is the degree of that monomial, and you’d write an entire polynomial as where ranges over all exponents you want.

**Definition: **Let be positive integers and be a prime power. The Reed-Muller code with parameters is defined as follows:

- The message is the list of multinomial coefficients of a homogeneous degree polynomial in variables, .
- You encode a message as the tuple of all polynomial evaluations .

Here the actual parameters of the code are , and being the number of possible coefficients. Finally , and we can prove this in the same way as we did for the Reed-Solomon code, using a beefed up fact about the number of roots of a multivariate polynomial:

**Fact: **Two multivariate degree polynomials over a finite field agree on at most an fraction of .

For messages of desired length , a clever choice of parameters gives a good code. Let , , and pick such that . Then the Reed-Muller code has polynomial length , and because we get that the distance of the code is asymptotically , i.e. it tends to .

A fun fact about Reed-Muller codes: they were apparently used on the Voyager space missions to relay image data back to Earth.

So we defined Reed-Solomon and Reed-Muller codes, but we didn’t really do any programming yet. The reason is because the encoding algorithms are very straightforward. If you’ve been following this blog you’ll know we have already written code to explicitly represent polynomials over finite fields, and extending that code to multivariable polynomials, at least for the sake of encoding the Reed-Muller code, is straightforward.

The real interesting algorithms come when you’re trying to decode. For example, in the Reed-Solomon code we’d take as input a bunch of points in a plane (over a finite field), only some of which are consistent with the underlying polynomial that generated them, and we have to reconstruct the unknown polynomial exactly. Even worse, for Reed-Muller we have to do it with many variables!

We’ll see exactly how to do that and produce working code next time.

Until then!

]]>

**Solution: **(in Python)

def majority(stream): held = next(stream) counter = 1 for item in stream: if item == held: counter += 1 elif counter == 0: held = item counter = 1 else: counter -= 1 return held

*Discussion: *Let’s prove correctness. Say that is the unknown value that occurs more than times. The idea of the algorithm is that if you could pair up elements of your stream so that *distinct *values are paired up, and then you “kill” these pairs, then will always survive. The way this algorithm pairs up the values is by holding onto the most recent value that has no pair (implicitly, by keeping a count how many copies of that value you saw). Then when you come across a new element, you decrement the counter and implicitly account for one new pair.

Let’s analyze the complexity of the algorithm. Clearly the algorithm only uses a single pass through the data. Next, if the stream has size , then this algorithm uses space. Indeed, if the stream entirely consists of a single value (say, a stream of all 1’s) then the counter will be at the end, which takes bits to store. On the other hand, if there are possible values then storing the largest requires bits.

Finally, the guarantee that one value occurs more than times is necessary. If it is not the case the algorithm could output anything (including the most *infrequent* element!). And moreover, if we don’t have this guarantee then *every algorithm *that solves the problem must use at least space in the worst case. In particular, say that , and the first items are all distinct and the last items are all the same one, the majority value . If you do not know in advance, then you must keep at least one bit of information to know which symbols occurred in the first half of the stream because any of them could be . So the guarantee allows us to bypass that barrier.

This algorithm can be generalized to detect items with frequency above some threshold using space . The idea is to keep counters instead of one, adding new elements when any counter is zero. When you see an element not being tracked by your counters (which are all positive), you decrement *all* the counters by 1. This is like a -to-one matching rather than a pairing.

]]>

Last time we made a quick tour through the main theorems of Claude Shannon, which essentially solved the following two problems about communicating over a digital channel.

- What is the best encoding for information when you are guaranteed that your communication channel is error free?
- Are there any encoding schemes that can recover from random noise introduced during transmission?

The answers to these questions were purely mathematical theorems, of course. But the interesting shortcoming of Shannon’s accomplishment was that his solution for the noisy coding problem (2) was nonconstructive. The question remains: can we actually come up with efficiently computable encoding schemes? The answer is yes! Marcel Golay was the first to discover such a code in 1949 (just a year after Shannon’s landmark paper), and Golay’s construction was published on a single page! We’re not going to define Golay’s code in this post, but we will mention its interesting status in coding theory later. The next year Richard Hamming discovered another simpler and larger family of codes, and went on to do some of the major founding work in coding theory. For his efforts he won a Turing Award and played a major part in bringing about the modern digital age. So we’ll start with Hamming’s codes.

We will assume some basic linear algebra knowledge, as detailed our first linear algebra primer. We will also use some basic facts about polynomials and finite fields, though the lazy reader can just imagine everything as binary and still grok the important stuff.

The formal definition of a code is simple: a *code* is just a subset of for some . Elements of are called *codewords.*

This is deceptively simple, but here’s the intuition. Say we know we want to send messages of length , so that our messages are in . Then we’re really viewing a code as the image of some encoding function . We can define by just describing what the set is, or we can define it by describing the encoding function. Either way, we will make sure that is an injective function, so that no two messages get sent to the same codeword. Then , and we can call the *message length* of even if we don’t have an explicit encoding function.

Moreover, while in this post we’ll always work with , the alphabet of your encoded messages could be an arbitrary set . So then a code would be a subset of tuples in , and we would call .

So we have these parameters , and we need one more. This is the *minimum distance* of a code, which we’ll denote by . This is defined to be the minimum Hamming distance between all distinct pairs of codewords, where by *Hamming distance *I just mean the number of coordinates that two tuples differ in. Recalling the remarks we made last time about Shannon’s nonconstructive proof, when we decode an encoded message (possibly with noisy bits) we look for the (unencoded) message whose encoding is as close to as possible. This will only work in the worst case if all pairs of codewords are sufficiently far apart. Hence we track the minimum distance of a code.

So coding theorists turn this mess of parameters into notation.

**Definition: **A code is called an -code if

- for some alphabet ,
- ,
- has minimum distance , and
- the alphabet has size .

The basic goals of coding theory are:

- For which values of these four parameters do codes exist?
- Fixing any three parameters, how can we optimize the other one?

In this post we’ll see how simple linear-algebraic constructions can give optima for one of these problems, optimizing for , and we’ll state a characterization theorem for optimizing for a general . Next time we’ll continue with a second construction that optimizes a different bound called the Singleton bound.

A code is called *linear* if it can be identified with a linear subspace of some finite-dimensional vector space. In this post all of our vector spaces will be , that is tuples of bits under addition mod 2. But you can do the same constructions with any finite scalar field for a prime power , i.e. have your vector space be . We’ll go back and forth between describing a binary code over and a code in $\mathbb{F}_q^n$. So to say a code is linear means:

- The zero vector is a codeword.
- The sum of any two codewords is a codeword.
- Any scalar multiple of a codeword is a codeword.

Linear codes are the simplest kinds of codes, but already they give a rich variety of things to study. The benefit of linear codes is that you can describe them in a lot of different and useful ways besides just describing the encoding function. We’ll use two that we define here. The idea is simple: you can describe everything about a linear subspace by giving a basis for the space.

**Definition: **A *generator matrix *of a -code is a matrix whose rows form a basis for .

There are a lot of equivalent generator matrices for a linear code (we’ll come back to this later), but the main benefit is that having a generator matrix allows one to encode messages by left multiplication . Intuitively, we can think of the bits of as describing the coefficients of the chosen linear combination of the rows of , which uniquely describes an element of the subspace. Note that because a -dimensional subspace of has elements, we’re not abusing notation by calling both the message length and the dimension.

For the second description of , we’ll remind the reader that every linear subspace has a unique *orthogonal complement* , which is the subspace of vectors that are orthogonal to vectors in .

**Definition: **Let be a generator matrix for . Then is called a *parity check* matrix.

Note has the basis for as *columns. *This means it has dimensions . Moreover, it has the property that *if and only if* the left multiplication . Having zero dot product with all columns of characterizes membership in .

The benefit of having a parity check matrix is that you can do efficient error detection: just compute on your received message , and if it’s nonzero there was an error! What if there were so many errors, and just the right errors that coincided with a different codeword than it started? Then you’re screwed. In other words, the parity check matrix is only guarantee to detect errors if you have fewer errors than the minimum distance of your code.

So that raises an obvious question: if you give me the generator matrix of a linear code can I compute its minimum distance? It turns out that this problem is NP-hard in general. In fact, you can show that this is equivalent to finding the smallest linearly *dependent* set of rows of the parity check matrix, and it is easier to see why such a problem might be hard. But if you construct your codes cleverly enough you can compute their distance properties with ease.

Before we do that, one more definition and a simple proposition about linear codes. The *Hamming weight* of a vector , denoted , is the number of nonzero entries in .

**Proposition: **The minimum distance of a linear code is the minimum Hamming weight over all nonzero vectors .

*Proof. *Consider a nonzero . On one hand, the zero vector is a codeword and is by definition the Hamming distance between and zero, so it is an upper bound on the minimum distance. In fact, it’s also a lower bound: if are two nonzero codewords, then is also a codeword and is the Hamming distance between and .

So now we can define our first code, the Hamming code. It will be a -code. The construction is quite simple. We have fixed , and we will also fix . One can think of this as fixing and maximizing , but it will only work for of a special form.

We’ll construct the Hamming code by describing a parity-check matrix . In fact, we’re going to see what conditions the minimum distance imposes on , and find out those conditions are actually sufficient to get . We’ll start with 2. If we want to ensure , then you need it to be the case that no nonzero vector of Hamming weight 1 is a code word. Indeed, if is a vector with all zeros except a one in position , then is the -th row of . We need , so this imposes the condition that no row of can be zero. It’s easy to see that this is sufficient for .

Likewise for , given a vector for some positions , then may not be zero. But because our sums are mod 2, saying that is the same as saying . Again it’s an if and only if. So we have the two conditions.

- No row of may be zero.
- All rows of must be distinct.

That is, *any *parity check matrix with those two properties defines a distance 3 linear code. The only question that remains is how large can be if the vectors have length ? That’s just the number of distinct nonzero binary strings of length , which is . Picking any way to arrange these strings as the rows of a matrix (say, in lexicographic order) gives you a good parity check matrix.

**Theorem: **For every , there is a -code called the *Hamming code.*

Since the Hamming code has distance 3, we can always detect if at most a single error occurs. Moreover, we can *correct* a single error using the Hamming code. If and is an error bit in position , then the incoming message would be . Now compute and flip bit of . That is, whichever row of you get tells you the index of the error, so you can flip the corresponding bit and correct it. If you order the rows lexicographically like we said, then as a binary number. Very slick.

Before we move on, we should note one interesting feature of linear codes.

**Definition:** A code is called *systematic* if it can be realized by an encoding function that appends some number “check bits” to the end of each message.

The interesting feature is that all linear codes are systematic. The reason is as follows. The generator matrix of a linear code has as rows a basis for the code as a linear subspace. We can perform Gaussian elimination on and get a new generator matrix that looks like where is the identity matrix of the appropriate size and is some junk. The point is that encoding using *this *generator matrix leaves the message unchanged, and adds a bunch of bits to the end that are determined by . It’s a different encoding function on , but it has the same image in , i.e. the code is unchanged. Gaussian elimination just performed a change of basis.

If you work out the parameters of the Hamming code, you’ll see that it is a systematic code which adds check bits to a message, and we’re able to correct a single error in this code. An obvious question is whether this is necessary? Could we get away with adding fewer check bits? The answer is no, and a simple “information theoretic” argument shows this. A single index out of requires bits to describe, and being able to correct a single error is like identifying a unique index. Without logarithmically many bits, you just don’t have enough information.

One nice fact about Hamming codes is that they optimize a natural problem: the problem of maximizing given a fixed choice of , , and . To get this let’s define denote the volume of a ball of radius in the space . I.e., if you fix any string (doesn’t matter which) , is the size of the set , where is the hamming distance.

There is a theorem called the *Hamming bound, *which describes a limit to how much you can pack disjoint balls of radius inside .

**Theorem: **If an -code exists, then

*Proof.* The proof is quite simple. To say a code has distance means that for every string there is no other string within Hamming distance of . In other words, the balls centered around both of radius are disjoint. The extra difference of one is for odd , e.g. when you need balls of radius 1 to guarantee no overlap. Now , so the total number of strings covered by all these balls is the left-hand side of the expression. But there are at most strings in , establishing the desired inequality.

Now a code is called *perfect *if it actually meets the Hamming bound exactly. As you probably guessed, the Hamming codes are perfect codes. It’s not hard to prove this, and I’m leaving it as an exercise to the reader.

The obvious follow-up question is whether there are any other perfect codes. The answer is yes, some of which are nonlinear. But some of them are “trivial.” For example, when you can just use the identity encoding to get the code . You can also just have a code which consists of a single codeword. There are also some codes that encode by repeating the message multiple times. These are called “repetition codes,” and all three of these examples are called *trivial *(as a definition). Now there are some nontrivial and nonlinear perfect codes I won’t describe here, but here is the nice characterization theorem.

**Theorem [van Lint ’71, Tietavainen ‘****73]: **Let be a nontrivial perfect code. Then the parameters must either be that of a Hamming code, or one of the two:

- A -code
- A -code

The last two examples are known as the *binary* and* ternary Golay codes*, respectively, which are also linear. In other words, every possible set of parameters for a perfect code can be realized as one of these three linear codes.

So this theorem was a big deal in coding theory. The Hamming and Golay codes were both discovered within a year of each other, in 1949 and 1950, but the nonexistence of other perfect linear codes was open for twenty more years. This wrapped up a very neat package.

Next time we’ll discuss the Singleton bound, which optimizes for a different quantity and is incomparable with perfect codes. We’ll define the Reed-Solomon and show they optimize this bound as well. These codes are particularly famous for being the error correcting codes used in DVDs. We’ll then discuss the algorithmic issues surrounding decoding, and more recent connections to complexity theory.

Until then!

]]>

- Say communication is very expensive. Then the problem is to come up with an encoding scheme for the messages which minimizes the expected length of an encoded message and guarantees the ability to unambiguously decode a message. This is called the
*noiseless coding problem.* - Say communication is not expensive, but error prone. In particular, each bit of your message is erroneously flipped with some known probably , and all the errors are independent. Then the question is, how can one encode their messages to as to guarantee (with high probability) the ability to decode any sent message? This is called the
*noisy coding problem.*

There are actually many models of “communication with noise” that generalize (2), such as models based on Markov chains. We are not going to cover them here.

Here is a simple example for the noiseless problem. Say you are just sending binary digits as your messages, and you know that the string “00000000” (eight zeros) occurs half the time, and all other eight-bit strings occur equally likely in the other half. It would make sense, then, to encode the “eight zeros” string as a 0, and prefix all other strings with a 1 to distinguish them from zero. You would save on average bits in every message.

One amazing thing about these two problems is that they were posed and solved in the same paper by Claude Shannon in 1948. One byproduct of his work was the notion of *entropy, *which in this context measures the “information content” of a message, or the expected “compressibility” of a single bit under the best encoding. For the extremely dedicated reader of this blog, note this differs from Kolmogorov complexity in that we’re not analyzing the compressibility of a string by itself, but rather when compared to a distribution. So really we should think of (the domain of) the distribution as being compressed, not the string.

Before we can state Shannon’s theorems we have to define entropy.

**Definition: **Suppose is a distribution on a finite set , and I’ll use to denote the probability of drawing from . The *entropy *of , denoted is defined as

It is strange to think about this sum in abstract, so let’s suppose is a biased coin flip with bias of landing heads. Then we can plot the entropy as follows

The horizontal axis is the bias , and the vertical axis is the value of , which with some algebra is . From the graph above we can see that the entropy is maximized when and minimized at . You can verify all of this with calculus, and you can prove that the uniform distribution maximizes entropy in general as well.

So what is this saying? A high entropy measures how *incompressible *something is, and low entropy gives us lots of compressibility. Indeed, if our message consisted of the results of 10 such coin flips, and was close to 1, we could be able to compress a lot by encoding strings with lots of 1’s using few bits. On the other hand, if we couldn’t get any compression at all. All strings would be equally likely.

Shannon’s famous theorem shows that the entropy of the distribution is actually all that matters. Some quick notation: is the set of all binary strings.

**Theorem (Noiseless Coding Theorem) [Shannon 1948]: **For every finite set and distribution over , there are encoding and decoding functions such that

- The encoding/decoding actually works, i.e. for all .
- The expected length of an encoded message is between and .

Moreover, *no encoding scheme can do better.*

Item 2 and the last sentence are the magical parts. In other words, if you know your distribution over messages, you *precisely* know how long to expect your messages to be. And you know that you can’t hope to do any better!

As the title of this post says, we aren’t going to give a proof here. Wikipedia has a proof if you’re really interested in the details.

The noisy coding problem is more interesting because in a certain sense (that was not solved by Shannon) it is still being studied today in the field of coding theory. The interpretation of the noisy coding problem is that you want to be able to recover from white noise errors introduced during transmission. The concept is called *error correction*. To restate what we said earlier, we want to recover from error with probability asymptotically close to 1, where the probability is over the errors.

It should be intuitively clear that you can’t do so without your encoding “blowing up” the length of the messages. Indeed, if your encoding does not blow up the message length then a single error will confound you since many valid messages would differ by only a single bit. So the question is does such an encoding exist, and if so how much do we need to blow up the message length? Shannon’s second theorem answers both questions.

**Theorem (Noisy Coding Theorem) [Shannon 1948]: **For any constant noise rate , there is an encoding scheme with the following property. If is the message sent by Alice, and is the message received by Bob (i.e. with random noise), then as a function of . In addition, if we denote by the entropy of the distribution of an error on a single bit, then choosing any guarantees the existence of such an encoding scheme, and no scheme exists for any smaller .

This theorem formalizes a “yes” answer to the noisy coding problem, but moreover it characterizes the blowup needed for such a scheme to exist. The deep fact is that *it only depends on the noise rate*.

A word about the proof: it’s probabilistic. That is, Shannon proved such an encoding scheme exists by picking to be a random function (!). Then finds (nonconstructively) the string such that the number of bits different between and is minimized. This “number of bits that differ” measure is called the *Hamming distance. *Then he showed using relatively standard probability tools that this scheme has the needed properties with high probability, the implication being that some scheme has to exist for such a probability to even be positive. The sharp threshold for takes a bit more work. If you want the details, check out the first few lectures of Madhu Sudan’s MIT class.

The non-algorithmic nature of his solution is what opened the door to more research. The question has surpassed, “Are there any encodings that work?” to the more interesting, “What is the algorithmic cost of constructing such an encoding?” It became a question of complexity, not computability. Moreover, the guarantees people wanted were strengthened to worst case guarantees. In other words, if I can guarantee *at most 12 errors*, is there an encoding scheme that will allow me to always recover the original message, and not just with high probability? One can imagine that if your message contains nuclear codes or your bank balance, you’d definitely want to have 100% recovery ability.

Indeed, two years later Richard Hamming spawned the theory of *error correcting codes *and defined codes that can always correct a single error. This theory has expanded and grown over the last sixty years, and these days the algorithmic problems of coding theory have deep connections to most areas of computer science, including learning theory, cryptography, and quantum computing.

We’ll cover Hamming’s basic codes next time, and then move on to Reed-Solomon codes and others. Until then!

]]>