Skip to content
The Lumenary
Advanced undergraduateUndergraduate (second or third year) 120 min

Information theory

How many bits does it take to describe a random message, and how fast can you send it through a noisy wire? Shannon's two answers — entropy and capacity — and the theorems that make them exact.

Formally verified · 15 LeanComputationally tested · 3 PythonAI-drafted · awaiting human reviewMathematically reviewed: Awaiting human review
MotivationH

Bits, noise and two questions

Morse code gives the most frequent letter of English, E, the shortest signal: a single dot. A text message sent from Lagos to Jakarta is compressed before it travels and protected against errors as it crosses radio links and cables; deep-space probes such as Voyager send their pictures home through extraordinary noise, protected by error-correcting codes; every QR code can be read even when part of it is torn off. Behind all of these is a 1948 paper by Claude Shannon, A Mathematical Theory of Communication, which asked two questions and answered both with numbers:

  1. Compression. A source emits random symbols. How many bits per symbol are needed, on average, to describe its output without loss? Answer: the entropy HH.
  2. Transmission. A channel corrupts what it carries. How many bits per use can be sent with arbitrarily small probability of error? Answer: the capacity CC.

Both answers are limits that can be approached but not beaten — theorems, not engineering rules of thumb. Shannon deliberately set meaning aside: "These semantic aspects of communication are irrelevant to the engineering problem." Information, in his sense, is resolved uncertainty. This lesson builds on probability theory, in particular expectation and the weak law of large numbers.

IntuitionH

Twenty questions and surprise

Someone picks a whole number from 11 to 6464. Each yes/no question can at best halve the remaining possibilities, so 6=log⁡2646 = \log_2 64 questions are needed and enough. More generally, singling out one of NN equally likely possibilities takes log⁡2N\log_2 N bits. If an outcome has probability pp, it is "one of 1/p1/p" possibilities, and learning that it happened gives

log⁡21p bits of information (its **surprisal**).\log_2\frac1p \text{ bits of information (its **surprisal**)}.

Rare events are surprising and informative; certain events tell us nothing. The entropy of a random variable is its average surprisal. For a coin with P(heads)=pP(\text{heads}) = p it is the binary entropy H2(p)=−plog⁡2p−(1−p)log⁡2(1−p)H_2(p) = -p\log_2 p - (1 - p)\log_2(1 - p): one full bit for a fair coin, less for a biased one, and zero for a coin that always lands heads.

Uncertainty and capacity

The entropy of a coin is largest when it is fair. A channel that flips each bit with probability p can carry 1 − H₂(p) bits per use: nothing at p = 1/2, and a full bit at p = 1, since a channel that always flips is as good as one that never does.

fair coin: 1 bitp ≈ 0.11: C ≈ 1/2
  • binary entropy H₂(p)
  • capacity 1 − H₂(p) of a channel flipping bits with probabili
  • binary entropy H₂(p): y = undefined here
  • capacity 1 − H₂(p) of a channel flipping bits with probabili: y = undefined here
DefinitionsH

Definitions

All random variables here take finitely many values. Logarithms are to base 22 (units: bits) unless stated; with natural logarithms the unit is the nat, and 11 nat =log⁡2e≈1.443= \log_2 e \approx 1.443 bits. We use the convention 0log⁡0=00\log 0 = 0 (justified by plog⁡p→0p\log p \to 0 as p→0p \to 0).

Definition— entropy, joint and conditional entropy

The entropy of XX with mass function pp is H(X)=−∑xp(x)log⁡p(x)=E[−log⁡p(X)]H(X) = -\sum_x p(x)\log p(x) = E[-\log p(X)]. For a pair (X,Y)(X, Y) with joint mass function p(x,y)p(x, y), the joint entropy is H(X,Y)=−∑x,yp(x,y)log⁡p(x,y)H(X, Y) = -\sum_{x,y}p(x, y)\log p(x, y), and the conditional entropy is

H(Y∣X)=∑xp(x) H(Y∣X=x)=−∑x,yp(x,y)log⁡p(y∣x).H(Y \mid X) = \sum_x p(x)\,H(Y \mid X = x) = -\sum_{x,y}p(x, y)\log p(y \mid x).

Definition— relative entropy and mutual information

For distributions p,qp, q on the same finite set, the relative entropy (Kullback–Leibler divergence) is D(p ∥ q)=∑xp(x)log⁡p(x)q(x)D(p \,\|\, q) = \sum_x p(x)\log\frac{p(x)}{q(x)} (infinite if q(x)=0<p(x)q(x) = 0 < p(x) for some xx). The mutual information of XX and YY is

I(X;Y)=H(X)−H(X∣Y),I(X; Y) = H(X) - H(X \mid Y),

the reduction in uncertainty about XX from learning YY.

Definition— prefix code

A binary code for a set X\mathcal X assigns to each symbol xx a codeword c(x)∈{0,1}∗c(x) \in \{0, 1\}^* of length ℓ(x)\ell(x). It is a prefix code (prefix-free) if no codeword is a prefix of another; then a concatenation of codewords can be decoded on the fly, without separators. Its expected length for a source with distribution pp is L=∑xp(x)ℓ(x)L = \sum_x p(x)\ell(x).

Definition— channel, rate and capacity

A discrete memoryless channel has input alphabet X\mathcal X, output alphabet Y\mathcal Y and transition probabilities W(y∣x)W(y \mid x); each use is independent of the others. A code of block length nn and rate RR consists of M=2nRM = 2^{nR} codewords in Xn\mathcal X^n and a decoding rule Yn→{1,…,M}\mathcal Y^n \to \{1, \dots, M\}. The capacity of the channel is

C=max⁡p(x)I(X;Y),C = \max_{p(x)} I(X; Y),

the maximum over input distributions of the mutual information between one input and its output.

Worked examplesH

Examples

Example— Dice, coins and text

A fair die has H=log⁡26≈2.585H = \log_2 6 \approx 2.585 bits; a coin with P(heads)=0.2P(\text{heads}) = 0.2 has H2(0.2)≈0.722H_2(0.2) \approx 0.722 bits. A source emitting A,B,C,DA, B, C, D with probabilities 12,14,18,18\tfrac12, \tfrac14, \tfrac18, \tfrac18 has H=12⋅1+14⋅2+18⋅3+18⋅3=1.75H = \tfrac12\cdot 1 + \tfrac14\cdot 2 + \tfrac18\cdot 3 + \tfrac18 \cdot 3 = 1.75 bits, and the prefix code A↦0A \mapsto 0, B↦10B \mapsto 10, C↦110C \mapsto 110, D↦111D \mapsto 111 achieves exactly 1.751.75 bits per symbol on average. The single-letter frequencies of English give about 4.14.1 bits per letter, but letters depend on their neighbours, and Shannon's 1951 experiments with human predictors suggested roughly 11 bit per letter once context is used.

ABCD010101
The prefix code 0, 10, 110, 111 as a binary tree: left branches are 0, right branches 1, and codewords are leaves. No codeword lies on the path to another, so the code is prefix-free; the leaf at depth $\ell$ takes up $2^{-\ell}$ of the tree, and the four leaves fill it exactly — Kraft's equality $\tfrac12 + \tfrac14 + \tfrac18 + \tfrac18 = 1$.

Example— Mutual information of a noisy bit

Let XX be a fair bit and YY the same bit sent through a channel that flips it with probability 14\tfrac14. Then YY is also a fair bit, H(X)=1H(X) = 1, and given YY the remaining uncertainty about XX is that of the flip: H(X∣Y)=H2(14)≈0.811H(X \mid Y) = H_2(\tfrac14) \approx 0.811. So I(X;Y)≈0.189I(X; Y) \approx 0.189 bits: each received bit tells us less than a fifth of a bit about what was sent. Repeating the transmission helps, at a cost in rate — the trade-off the channel coding theorem resolves.

ProofH

Gibbs' inequality and its consequences

Everything rests on one inequality, which comes from ln⁡t≤t−1\ln t \le t - 1 (with equality only at t=1t = 1): the tangent line at t=1t = 1 lies above the concave function ln⁡\ln.

Theorem— Theorem (Gibbs' inequality)

For distributions pp and qq on a finite set, D(p ∥ q)≥0D(p \,\|\, q) \ge 0, with equality if and only if p=qp = q. More generally, if q≥0q \ge 0 with ∑xq(x)≤1\sum_x q(x) \le 1, then ∑xp(x)log⁡q(x)p(x)≤0\sum_x p(x)\log\frac{q(x)}{p(x)} \le 0.

Proof

We may assume q(x)>0q(x) > 0 whenever p(x)>0p(x) > 0 (otherwise D=∞D = \infty). Working in nats, for each xx with p(x)>0p(x) > 0,   p(x)ln⁡q(x)p(x)≤p(x)(q(x)p(x)−1)=q(x)−p(x)\;p(x)\ln\frac{q(x)}{p(x)} \le p(x)\Big(\frac{q(x)}{p(x)} - 1\Big) = q(x) - p(x), and terms with p(x)=0p(x) = 0 contribute 0≤q(x)0 \le q(x). Summing,

∑xp(x)ln⁡q(x)p(x)≤∑xq(x)−∑xp(x)≤1−1=0.\sum_x p(x)\ln\frac{q(x)}{p(x)} \le \sum_x q(x) - \sum_x p(x) \le 1 - 1 = 0 .

Equality forces q(x)p(x)=1\frac{q(x)}{p(x)} = 1 wherever p(x)>0p(x) > 0 and ∑xq(x)=1\sum_x q(x) = 1, hence p=qp = q. Changing the base of the logarithm multiplies everything by a positive constant.

∎

Theorem— Corollary (bounds and chain rule)

  1. 0≤H(X)≤log⁡∣X∣0 \le H(X) \le \log|\mathcal X|, with H(X)=0H(X) = 0 iff XX is constant and H(X)=log⁡∣X∣H(X) = \log|\mathcal X| iff XX is uniform.
  2. Chain rule: H(X,Y)=H(X)+H(Y∣X)H(X, Y) = H(X) + H(Y \mid X).
  3. I(X;Y)=H(X)+H(Y)−H(X,Y)=D(pXY ∥ pXpY)I(X; Y) = H(X) + H(Y) - H(X, Y) = D\big(p_{XY} \,\big\|\, p_Xp_Y\big). Hence I(X;Y)=I(Y;X)≥0I(X; Y) = I(Y; X) \ge 0, with equality iff XX and YY are independent; equivalently H(X∣Y)≤H(X)H(X \mid Y) \le H(X) — conditioning reduces entropy on average.

Proof

(1) Each term −plog⁡p-p\log p is ≥0\ge 0 for 0≤p≤10 \le p \le 1, and vanishes only at p∈{0,1}p \in \{0, 1\}. For the upper bound apply Gibbs with qq uniform: 0≥∑xp(x)log⁡1∣X∣p(x)=H(X)−log⁡∣X∣0 \ge \sum_x p(x)\log\frac{1}{|\mathcal X|p(x)} = H(X) - \log|\mathcal X|, with equality iff pp is uniform.

(2) Write p(x,y)=p(x)p(y∣x)p(x, y) = p(x)p(y \mid x) and take −E[log⁡(⋅)]-E[\log(\cdot)]: H(X,Y)=E[−log⁡p(X)]+E[−log⁡p(Y∣X)]=H(X)+H(Y∣X)H(X, Y) = E[-\log p(X)] + E[-\log p(Y \mid X)] = H(X) + H(Y \mid X).

(3) By the chain rule (with the roles of XX and YY swapped), H(X∣Y)=H(X,Y)−H(Y)H(X \mid Y) = H(X, Y) - H(Y), so I(X;Y)=H(X)+H(Y)−H(X,Y)I(X; Y) = H(X) + H(Y) - H(X, Y), which is symmetric. Writing the three entropies as expectations, I(X;Y)=E[log⁡p(X,Y)p(X)p(Y)]=D(pXY ∥ pXpY)I(X; Y) = E\Big[\log\frac{p(X, Y)}{p(X)p(Y)}\Big] = D(p_{XY} \,\|\, p_Xp_Y), and Gibbs' inequality finishes the proof.

∎

Theorem— Theorem (data-processing inequality)

If X→Y→ZX \to Y \to Z is a Markov chain (ZZ depends on XX only through YY), then I(X;Z)≤I(X;Y)I(X; Z) \le I(X; Y): no processing of YY, deterministic or random, can increase the information it carries about XX.

Proof

Define conditional mutual information I(X;Y∣Z)=H(X∣Z)−H(X∣Y,Z)≥0I(X; Y \mid Z) = H(X \mid Z) - H(X \mid Y, Z) \ge 0 (Gibbs again, conditionally on each value of ZZ). The chain rule gives I(X;Y,Z)=I(X;Z)+I(X;Y∣Z)=I(X;Y)+I(X;Z∣Y)I(X; Y, Z) = I(X; Z) + I(X; Y \mid Z) = I(X; Y) + I(X; Z \mid Y). The Markov property makes XX and ZZ conditionally independent given YY, so I(X;Z∣Y)=0I(X; Z \mid Y) = 0, and therefore I(X;Z)≤I(X;Y)I(X; Z) \le I(X; Y).

∎

Why this formula for entropy, and not another? Shannon showed, and Khinchin (1953) made rigorous, that any function of probability vectors that is continuous, maximal at the uniform distribution, unchanged by adding impossible outcomes, and additive in the sense of the chain rule must be a positive multiple of −∑plog⁡p-\sum p\log p. The choice of base is the choice of unit.

ProofH

Prefix codes, Kraft and Huffman

A binary word ww of length ℓ\ell corresponds to the dyadic interval J(w)=[0.w, 0.w+2−ℓ)J(w) = [0.w,\ 0.w + 2^{-\ell}) of [0,1)[0, 1), where 0.w0.w is the binary fraction with digits ww; and uu is a prefix of vv exactly when J(v)⊆J(u)J(v) \subseteq J(u). Two dyadic intervals are either nested or disjoint, so a code is prefix-free exactly when its intervals are pairwise disjoint.

Theorem— Theorem (Kraft's inequality, 1949)

A binary prefix code with codeword lengths ℓ1,…,ℓk\ell_1, \dots, \ell_k exists if and only if ∑i=1k2−ℓi≤1\sum_{i=1}^k 2^{-\ell_i} \le 1.

Proof

Necessity. The intervals J(ci)J(c_i) of a prefix code are disjoint subsets of [0,1)[0, 1) with lengths 2−ℓi2^{-\ell_i}, so their total length is at most 11. (The Lean proof argues instead by induction on the maximal length, splitting the code by its first bit.)

Sufficiency. Order the lengths ℓ1≤⋯≤ℓk\ell_1 \le \cdots \le \ell_k and put ai=∑j<i2−ℓja_i = \sum_{j < i}2^{-\ell_j}. Since ℓj≤ℓi\ell_j \le \ell_i for j<ij < i, aia_i is a multiple of 2−ℓi2^{-\ell_i}, and ai+2−ℓi≤∑j2−ℓj≤1a_i + 2^{-\ell_i} \le \sum_j 2^{-\ell_j} \le 1; so ai=0.cia_i = 0.c_i for a word cic_i of exactly ℓi\ell_i digits, and J(ci)=[ai,ai+1)J(c_i) = [a_i, a_{i+1}). These intervals are disjoint, so the code is prefix-free.

∎

McMillan (1956) showed that the same inequality holds for every uniquely decodable code, so nothing is lost by insisting on prefix codes.

Theorem— Theorem (source coding bounds)

The minimal expected length L∗L^* of a binary prefix code for a source XX satisfies H(X)≤L∗<H(X)+1H(X) \le L^* < H(X) + 1.

Proof

Lower bound. Given a prefix code, put q(x)=2−ℓ(x)q(x) = 2^{-\ell(x)}, so ∑xq(x)≤1\sum_x q(x) \le 1 by Kraft. Gibbs' inequality gives ∑xp(x)log⁡22−ℓ(x)p(x)≤0\sum_x p(x)\log_2\frac{2^{-\ell(x)}}{p(x)} \le 0, that is, H(X)−L≤0H(X) - L \le 0.

Upper bound. Take Shannon's lengths ℓ(x)=⌈−log⁡2p(x)⌉\ell(x) = \lceil -\log_2 p(x)\rceil (for p(x)>0p(x) > 0). Then 2−ℓ(x)≤p(x)2^{-\ell(x)} \le p(x), so ∑x2−ℓ(x)≤1\sum_x 2^{-\ell(x)} \le 1 and by Kraft a prefix code with these lengths exists; and ℓ(x)<−log⁡2p(x)+1\ell(x) < -\log_2 p(x) + 1, so L<H(X)+1L < H(X) + 1.

∎

Coding blocks of nn symbols at once spreads the "+1+1" over nn symbols: for an i.i.d. source, H(Xn)=nH(X)H(X^n) = nH(X), so the optimal code for blocks has H(X)≤Ln∗/n<H(X)+1nH(X) \le L^*_n/n < H(X) + \frac1n. The entropy is the exact price of lossless description. Shannon's lengths are not optimal, though; the optimal code comes from a simple greedy algorithm.

Huffman's algorithm (1952). Take the two least probable symbols, make them siblings — their codewords will differ only in the last bit — and replace them by a single symbol whose probability is their sum. Repeat until one symbol remains; reading the merges backwards builds the code tree.

Theorem— Theorem (Huffman codes are optimal)

A Huffman code has the smallest expected length among all binary prefix codes for the given distribution.

Proof

Induction on the number kk of symbols; k=2k = 2 is clear (lengths 1,11, 1). Let x,yx, y be the two least probable symbols.

Step 1: some optimal code has xx and yy as sibling leaves at maximal depth. In an optimal code, if p(a)>p(b)p(a) > p(b) then ℓ(a)≤ℓ(b)\ell(a) \le \ell(b) (otherwise swapping their codewords lowers LL). The code tree of an optimal code is full — every internal node has two children — since otherwise a codeword could be shortened. So a deepest leaf has a sibling leaf; exchanging codewords so that xx and yy occupy these two leaves does not increase LL, because they are the least probable.

Step 2: merging. Replace x,yx, y by one symbol zz with p(z)=p(x)+p(y)p(z) = p(x) + p(y). Codes for the original source in which x,yx, y are siblings correspond to codes for the merged source (delete the last bit of their codewords to get zz's), and L=L′+p(x)+p(y)L = L' + p(x) + p(y). So an optimal code for the merged source, extended by one bit, is optimal among codes with x,yx, y siblings — hence, by Step 1, optimal. Huffman's algorithm does exactly this, and by induction it produces an optimal code for the merged source.

∎

A Huffman tree is full, so its lengths satisfy Kraft with equality. The first experiment below builds one for a real sentence and checks every bound.

ExplanationH

Typical sequences and Shannon's source coding theorem

For an i.i.d. source, −log⁡2p(X1,…,Xn)=∑i=1n−log⁡2p(Xi)-\log_2 p(X_1, \dots, X_n) = \sum_{i=1}^n -\log_2 p(X_i) is a sum of i.i.d. terms with mean H(X)H(X), so by the weak law of large numbers:

Theorem— Theorem (asymptotic equipartition property)

If X1,X2,…X_1, X_2, \dots are i.i.d. with entropy HH, then −1nlog⁡2p(X1,…,Xn)→H-\frac1n\log_2 p(X_1, \dots, X_n) \to H in probability.

So with high probability the sequence that occurs has probability close to 2−nH2^{-nH}. Fix ε>0\varepsilon > 0 and let the typical set Tε(n)T_\varepsilon^{(n)} consist of the sequences with 2−n(H+ε)≤p(x1,…,xn)≤2−n(H−ε)2^{-n(H + \varepsilon)} \le p(x_1, \dots, x_n) \le 2^{-n(H - \varepsilon)}. Then (i) P(Tε(n))→1P(T_\varepsilon^{(n)}) \to 1; (ii) ∣Tε(n)∣≤2n(H+ε)|T_\varepsilon^{(n)}| \le 2^{n(H + \varepsilon)}, because each of its elements has probability at least 2−n(H+ε)2^{-n(H+\varepsilon)} and the total is at most 11; and (iii) ∣Tε(n)∣≥(1−ε)2n(H−ε)|T_\varepsilon^{(n)}| \ge (1 - \varepsilon)2^{n(H - \varepsilon)} for large nn. Almost all the probability sits on about 2nH2^{nH} roughly equiprobable sequences — a vanishing fraction of all ∣X∣n|\mathcal X|^n sequences when H<log⁡∣X∣H < \log|\mathcal X|.

Theorem— Theorem (Shannon's source coding theorem)

For an i.i.d. source with entropy HH: for every R>HR > H there are codes mapping blocks of nn symbols to nRnR bits whose probability of decoding error tends to 00 as n→∞n \to \infty; for every R<HR < H, the probability of error of any such codes tends to 11.

Sketch. Index the typical set with n(H+ε)+1n(H + \varepsilon) + 1 bits and give up on the rest; the error probability is 1−P(Tε(n))→01 - P(T_\varepsilon^{(n)}) \to 0. Conversely, 2nR2^{nR} codewords with R<HR < H can cover at most 2nR2^{nR} typical sequences, whose total probability is at most 2nR2−n(H−ε)→02^{nR}2^{-n(H - \varepsilon)} \to 0, plus the vanishing probability outside the typical set. The second experiment below measures typical sets exactly for a biased coin.

ProofH

Channels and capacity

Theorem— Theorem (capacity of the binary symmetric channel)

The binary symmetric channel with crossover probability pp (each bit flipped independently with probability pp) has capacity C=1−H2(p)C = 1 - H_2(p) bits per use, attained by the uniform input.

Proof

Let P(X=1)=sP(X = 1) = s. Given X=xX = x, the output is xx or 1−x1 - x with probabilities 1−p1 - p and pp, so H(Y∣X=x)=H2(p)H(Y \mid X = x) = H_2(p) for both xx, and H(Y∣X)=H2(p)H(Y \mid X) = H_2(p). The output is 11 with probability s(1−p)+(1−s)ps(1 - p) + (1 - s)p, so

I(X;Y)=H(Y)−H(Y∣X)=H2(s(1−p)+(1−s)p)−H2(p)≤1−H2(p),I(X; Y) = H(Y) - H(Y \mid X) = H_2\big(s(1-p) + (1-s)p\big) - H_2(p) \le 1 - H_2(p),

since a binary variable has entropy at most 11 bit. For s=12s = \frac12 the output probability is 12\frac12 and equality holds.

∎

Similarly, the binary erasure channel, which delivers each bit correctly with probability 1−ε1 - \varepsilon and otherwise replaces it by "?", has capacity 1−ε1 - \varepsilon: an erasure is known to the receiver, and with feedback one could simply resend; Shannon's theorem says the same rate is achievable without feedback.

WW
XnX^n
YnY^n
W^\hat W
encoder\text{encoder}
channel W(y∣x)\text{channel } W(y \mid x)
decoder\text{decoder}
A message WW (one of 2nR2^{nR}) is encoded as nn channel inputs, corrupted by the channel (dashed: random), and decoded as W^\hat W. The chain W→Xn→Yn→W^W \to X^n \to Y^n \to \hat W is a Markov chain, so the data-processing inequality applies.

Theorem— Theorem (noisy-channel coding theorem, Shannon 1948)

Let CC be the capacity of a discrete memoryless channel.

  • Achievability. For every R<CR < C and ε>0\varepsilon > 0, for all sufficiently large nn there is a code of block length nn and rate at least RR whose maximal probability of decoding error is at most ε\varepsilon.
  • Converse. For every sequence of codes with rate R>CR > C, the average probability of error is bounded away from 00 (indeed Pe(n)≥1−CR−1nRP_e^{(n)} \ge 1 - \frac CR - \frac{1}{nR}).

Sketch of the proof. Converse: for a uniformly random message WW of nRnR bits, Fano's inequality bounds the leftover uncertainty, H(W∣W^)≤1+Pe nRH(W \mid \hat W) \le 1 + P_e\,nR; the data-processing inequality and memorylessness give I(W;W^)≤I(Xn;Yn)≤nCI(W; \hat W) \le I(X^n; Y^n) \le nC; and nR=H(W)=H(W∣W^)+I(W;W^)≤1+Pe nR+nCnR = H(W) = H(W \mid \hat W) + I(W; \hat W) \le 1 + P_e\,nR + nC, which rearranges to the stated bound. Achievability: Shannon's astonishing idea was to choose the codebook at random — 2nR2^{nR} codewords drawn independently from the capacity-achieving input distribution — and to decode by looking for the unique codeword jointly typical with the output. The AEP shows that the true codeword is jointly typical with high probability, while any particular wrong codeword is jointly typical with probability about 2−nI(X;Y)2^{-nI(X;Y)}; with 2nR2^{nR} wrong codewords and R<I(X;Y)R < I(X; Y), the union bound makes a confusion unlikely. Since the average over random codebooks has small error, some codebook does too, and discarding its worst half bounds the maximal error. Full proofs: Cover and Thomas, Chapter 7.

The theorem is an existence theorem. Repetition codes achieve small error only by letting the rate 1/n1/n go to zero; the Hamming (7,4)(7, 4) code (1950) sends 44 bits in 77 and corrects any single error. Codes that approach capacity with practical decoding took decades: low-density parity-check codes (Gallager, 1962; rediscovered in the 1990s), turbo codes (Berrou, Glavieux and Thitimajshima, 1993) and polar codes (Arıkan, 2009), now used in mobile networks. The third experiment compares repetition codes and the Hamming code with the capacity.

Formal mathematicsF

Information theory in Lean and Mathlib

Mathlib works in nats: Real.negMulLog x = −x log x and the binary entropy Real.binEntropy p use natural logarithms, so log 2 nats is one bit. The module defines entropy for distributions on a finite type and proves the lesson's core inequalities.

Entropy and Gibbs' inequality, proved as in the lesson from log t ≤ t − 1, and the bound H≤log⁡∣X∣H \le \log|\mathcal X|:

entropyLean 4Formally verified
/-- The **Shannon entropy** of a distribution `p` on a finite set, in nats:
`H(p) = −∑ p(x) log p(x) = ∑ negMulLog (p x)`. (Lean's convention `log 0 = 0` gives the
usual `0 log 0 = 0`.) -/
noncomputable def entropy (p : S → ℝ) : ℝ := ∑ x, negMulLog (p x)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
entropy_nonnegLean 4Proved here from basic factsFormally verified
/-- **Entropy is non-negative**: each term `−p log p` is `≥ 0` for `0 ≤ p ≤ 1` (Mathlib's
`Real.negMulLog_nonneg`). It is `0` exactly for a point mass: no uncertainty. -/
theorem entropy_nonneg {p : S → ℝ} (h0 : ∀ x, 0 ≤ p x) (h1 : ∀ x, p x ≤ 1) :
    0 ≤ entropy p :=
  sum_nonneg fun x _ => negMulLog_nonneg (h0 x) (h1 x)
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
gibbsLean 4Proved here from basic factsFormally verified
/-- **Gibbs' inequality.** If `p` is a distribution and `q > 0` with `∑ q ≤ 1`, then
`∑ p(x) log (q(x)/p(x)) ≤ 0`; equivalently the relative entropy
`D(p ‖ q) = ∑ p log (p/q)` is non-negative. Proof, as in the lesson: termwise
`p log (q/p) ≤ p (q/p − 1) = q − p` by `log t ≤ t − 1` (and `0 ≤ q` when `p = 0`); summing,
`∑ (q − p) = ∑ q − 1 ≤ 0`. -/
theorem gibbs {p q : S → ℝ} (hp0 : ∀ x, 0 ≤ p x) (hp1 : ∑ x, p x = 1) (hq : ∀ x, 0 < q x)
    (hq1 : ∑ x, q x ≤ 1) : ∑ x, p x * log (q x / p x) ≤ 0 := by
  have hterm : ∀ x, p x * log (q x / p x) ≤ q x - p x := by
    intro x
    rcases (hp0 x).lt_or_eq with hpos | hzero
    · have := log_le_sub_one_of_pos (div_pos (hq x) hpos)
      calc p x * log (q x / p x) ≤ p x * (q x / p x - 1) :=
            mul_le_mul_of_nonneg_left this hpos.le
        _ = q x - p x := by field_simp
    · rw [← hzero]
      simp [(hq x).le]
  calc ∑ x, p x * log (q x / p x) ≤ ∑ x, (q x - p x) := sum_le_sum fun x _ => hterm x
    _ = ∑ x, q x - ∑ x, p x := sum_sub_distrib _ _
    _ ≤ 0 := by linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
entropy_le_log_cardLean 4Proved here from basic factsFormally verified
/-- **Entropy is at most `log |𝒳|`**, with the uniform distribution as the extreme case.
Proof: Gibbs' inequality with `q` uniform, `q(x) = 1/|𝒳|`:
`0 ≥ ∑ p log (1/(|𝒳| p)) = H(p) − log |𝒳|`. -/
theorem entropy_le_log_card [Nonempty S] {p : S → ℝ} (hp0 : ∀ x, 0 ≤ p x)
    (hp1 : ∑ x, p x = 1) : entropy p ≤ log (Fintype.card S) := by
  set n : ℝ := (Fintype.card S : ℝ)
  have hn : 0 < n := by
    simp only [n]
    exact_mod_cast (Fintype.card_pos : 0 < Fintype.card S)
  have hq1 : ∑ _x : S, (1 / n) ≤ 1 := by
    rw [sum_const, card_univ, nsmul_eq_mul]
    simp only [n]
    field_simp
    exact le_refl _
  have hg := gibbs (q := fun _ => 1 / n) hp0 hp1 (fun _ => by positivity) hq1
  -- Each term splits: `p log (1/(n p)) = −p log p − p log n`.
  have hsplit : ∀ x, p x * log ((1 / n) / p x) = negMulLog (p x) - p x * log n := by
    intro x
    rcases (hp0 x).lt_or_eq with hpos | hzero
    · rw [negMulLog, div_div, one_div, log_inv, log_mul hn.ne' hpos.ne']
      ring
    · rw [← hzero]
      simp [negMulLog]
  simp only [hsplit, sum_sub_distrib, ← sum_mul, hp1, one_mul] at hg
  unfold entropy
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

Binary entropy from Mathlib: at most one bit, with equality exactly for a fair coin.

binEntropy_le_log_two'Lean 4Applies a library theoremFormally verified
/-- The binary entropy `h(p) = −p log p − (1 − p) log (1 − p)` is at most `log 2` (one bit).
This is Mathlib's `Real.binEntropy_le_log_two`. -/
theorem binEntropy_le_log_two' (p : ℝ) : binEntropy p ≤ log 2 :=
  binEntropy_le_log_two
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
binEntropy_eq_log_two_iffLean 4Applies a library theoremFormally verified
/-- …with equality exactly at `p = 1/2`: a fair coin carries one full bit. This is Mathlib's
`Real.binEntropy_eq_log_two`. -/
theorem binEntropy_eq_log_two_iff (p : ℝ) : binEntropy p = log 2 ↔ p = 2⁻¹ :=
  binEntropy_eq_log_two
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

The binary symmetric channel. The mutual information as a function of the input distribution (its formula is derived in the lesson and taken as the definition), its upper bound, and the input that attains it:

bscInfoLean 4Formally verified
/-- The mutual information `I(X; Y)` of a **binary symmetric channel** with crossover
probability `p`, when the input is `1` with probability `s`: the output is `1` with probability
`s(1 − p) + (1 − s)p`, so `H(Y) = h(s(1 − p) + (1 − s)p)`, while `H(Y | X) = h(p)` whatever
the input. Hence `I = H(Y) − H(Y | X)`. (This derivation is in the lesson; here it is the
definition.) -/
noncomputable def bscInfo (p s : ℝ) : ℝ := binEntropy (s * (1 - p) + (1 - s) * p) - binEntropy p
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
bsc_info_leLean 4Proved here from basic factsFormally verified
/-- For every input distribution, `I(X; Y) ≤ log 2 − h(p)`, because `H(Y) ≤ log 2`. -/
theorem bsc_info_le (p s : ℝ) : bscInfo p s ≤ log 2 - binEntropy p := by
  unfold bscInfo
  linarith [binEntropy_le_log_two (p := s * (1 - p) + (1 - s) * p)]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
bsc_capacityLean 4Proved here from basic factsFormally verified
/-- **The capacity of the binary symmetric channel is `log 2 − h(p)` nats, i.e. `1 − H₂(p)`
bits**: the bound of `bsc_info_le` is attained by the uniform input `s = 1/2`, which makes the
output uniform too. -/
theorem bsc_capacity (p : ℝ) : bscInfo p (1 / 2) = log 2 - binEntropy p := by
  unfold bscInfo
  have : (1 / 2 : ℝ) * (1 - p) + (1 - 1 / 2) * p = 2⁻¹ := by ring
  rw [this, (binEntropy_eq_log_two).mpr rfl]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

Prefix codes. Kraft's inequality for every finite prefix-free set of binary words, by induction on the maximal length:

PrefixFreeLean 4Formally verified
/-- A set of binary codewords is **prefix-free** if no codeword is a proper beginning of
another: `u <+: v` (`u` is a prefix of `v`) forces `u = v`. Such a code can be decoded on the
fly, without separators. -/
def PrefixFree (C : Finset (List Bool)) : Prop :=
  ∀ u ∈ C, ∀ v ∈ C, u <+: v → u = v
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
kraftLean 4Proved here from basic factsFormally verified
/-- **Kraft's inequality.** For every finite prefix-free set `C` of binary words,
`∑_{w ∈ C} 2^{−|w|} ≤ 1`. Proof by induction on the maximum length `L`: if the empty word is
in `C`, prefix-freeness forces `C = {[]}`; otherwise split `C` by first bit into `0·C₀` and
`1·C₁`, where `C₀, C₁` are prefix-free with words of length `≤ L − 1`, so
`∑_C 2^{−|w|} = ½ ∑_{C₀} + ½ ∑_{C₁} ≤ ½ + ½`. -/
theorem kraft : ∀ (L : ℕ) (C : Finset (List Bool)), (∀ w ∈ C, w.length ≤ L) → PrefixFree C →
    ∑ w ∈ C, (1 / 2 : ℝ) ^ w.length ≤ 1 := by
  intro L
  induction L with
  | zero =>
    intro C hlen _
    have hsub : C ⊆ {[]} := by
      intro w hw
      have := hlen w hw
      simp_all [List.length_eq_zero_iff]
    calc ∑ w ∈ C, (1 / 2 : ℝ) ^ w.length ≤ ∑ w ∈ ({[]} : Finset (List Bool)),
          (1 / 2 : ℝ) ^ w.length := sum_le_sum_of_subset_of_nonneg hsub (fun _ _ _ => by positivity)
      _ = 1 := by simp
  | succ L ih =>
    intro C hlen hpf
    by_cases hnil : [] ∈ C
    · -- The empty word is a prefix of everything, so `C = {[]}`.
      have hC : C = {[]} := by
        ext w
        simp only [mem_singleton]
        constructor
        · intro hw
          exact (hpf [] hnil w hw (List.nil_prefix)).symm
        · rintro rfl
          exact hnil
      simp [hC]
    · -- Split by the first bit.
      let part : Bool → Finset (List Bool) := fun b =>
        (C.filter (fun w => w.head? = some b)).image List.tail
      have hpart_len : ∀ b, ∀ t ∈ part b, t.length ≤ L := by
        intro b t ht
        simp only [part, mem_image, mem_filter] at ht
        obtain ⟨w, ⟨hw, _⟩, rfl⟩ := ht
        have := hlen w hw
        rw [List.length_tail]
        omega
      have hcons : ∀ b, ∀ w ∈ C.filter (fun w => w.head? = some b), w = b :: w.tail := by
        intro b w hw
        simp only [mem_filter] at hw
        cases w with
        | nil => simp at hw
        | cons a t =>
          simp only [List.head?_cons, Option.some.injEq] at hw
          rw [hw.2]
          rfl
      have hpart_pf : ∀ b, PrefixFree (part b) := by
        intro b u hu v hv huv
        simp only [part, mem_image] at hu hv
        obtain ⟨u', hu', rfl⟩ := hu
        obtain ⟨v', hv', rfl⟩ := hv
        have hu'' := hcons b u' hu'
        have hv'' := hcons b v' hv'
        have hpre : u' <+: v' := by
          rw [hu'', hv'']
          exact (List.prefix_cons_inj b).mpr huv
        have := hpf u' (mem_filter.mp hu').1 v' (mem_filter.mp hv').1 hpre
        rw [this]
      have hpart_sum : ∀ b, ∑ w ∈ C.filter (fun w => w.head? = some b), (1 / 2 : ℝ) ^ w.length =
          1 / 2 * ∑ t ∈ part b, (1 / 2 : ℝ) ^ t.length := by
        intro b
        rw [sum_image]
        · rw [mul_sum]
          refine sum_congr rfl fun w hw => ?_
          rw [hcons b w hw]
          simp [pow_succ]
          ring
        · intro x hx y hy hxy
          rw [hcons b x hx, hcons b y hy, hxy]
      -- Every word of `C` starts with `false` or `true`.
      have hsplit : ∑ w ∈ C, (1 / 2 : ℝ) ^ w.length =
          ∑ w ∈ C.filter (fun w => w.head? = some false), (1 / 2 : ℝ) ^ w.length +
          ∑ w ∈ C.filter (fun w => w.head? = some true), (1 / 2 : ℝ) ^ w.length := by
        rw [← sum_union]
        · congr 1
          ext w
          simp only [mem_union, mem_filter]
          constructor
          · intro hw
            cases w with
            | nil => exact absurd hw hnil
            | cons a t => cases a <;> simp [hw]
          · rintro (⟨hw, _⟩ | ⟨hw, _⟩) <;> exact hw
        · rw [disjoint_left]
          intro w h1 h2
          simp only [mem_filter] at h1 h2
          rw [h1.2] at h2
          simp at h2
      rw [hsplit, hpart_sum false, hpart_sum true]
      have h0 := ih (part false) (hpart_len false) (hpart_pf false)
      have h1 := ih (part true) (hpart_len true) (hpart_pf true)
      linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

Source coding bounds. Any lengths satisfying Kraft have expected length at least HH; Shannon's lengths satisfy Kraft and come within one bit of HH:

source_coding_lowerLean 4Proved here from basic factsFormally verified
/-- **No prefix code beats the entropy.** If codeword lengths `ℓ(x)` satisfy Kraft's
inequality `∑ 2^{−ℓ(x)} ≤ 1`, then the expected length is at least the entropy:
`H(p) ≤ (∑ p(x) ℓ(x)) · log 2` (in bits: `L ≥ H₂`). Proof: Gibbs' inequality with
`q(x) = 2^{−ℓ(x)}`. -/
theorem source_coding_lower {p : S → ℝ} (hp0 : ∀ x, 0 ≤ p x) (hp1 : ∑ x, p x = 1)
    (ℓ : S → ℕ) (hkraft : ∑ x, (1 / 2 : ℝ) ^ ℓ x ≤ 1) :
    entropy p ≤ (∑ x, p x * ℓ x) * log 2 := by
  have hg := gibbs (q := fun x => (1 / 2 : ℝ) ^ ℓ x) hp0 hp1 (fun x => by positivity) hkraft
  have hsplit : ∀ x, p x * log ((1 / 2 : ℝ) ^ ℓ x / p x) =
      negMulLog (p x) - p x * ℓ x * log 2 := by
    intro x
    rcases (hp0 x).lt_or_eq with hpos | hzero
    · rw [log_div (by positivity) hpos.ne', log_pow, one_div, log_inv, negMulLog]
      ring
    · rw [← hzero]
      simp [negMulLog]
  simp only [hsplit, sum_sub_distrib] at hg
  unfold entropy
  rw [sum_mul]
  linarith
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
shannon_lengths_kraftLean 4Proved here from basic factsFormally verified
/-- **Shannon's code lengths satisfy Kraft.** For a distribution with all `p(x) > 0`, the
lengths `ℓ(x) = ⌈−log₂ p(x)⌉` satisfy `2^{−ℓ(x)} ≤ p(x)`, hence `∑ 2^{−ℓ(x)} ≤ 1`, so (by
the converse of Kraft) a prefix code with these lengths exists. -/
theorem shannon_lengths_kraft {p : S → ℝ} (hp : ∀ x, 0 < p x) (hp1 : ∑ x, p x = 1) :
    ∑ x, (1 / 2 : ℝ) ^ ⌈-logb 2 (p x)⌉₊ ≤ 1 := by
  have hterm : ∀ x, (1 / 2 : ℝ) ^ ⌈-logb 2 (p x)⌉₊ ≤ p x := by
    intro x
    have hceil : -logb 2 (p x) ≤ ⌈-logb 2 (p x)⌉₊ := Nat.le_ceil _
    -- `(1/2)^ℓ = 2^(−ℓ) ≤ 2^(logb 2 p) = p`.
    have h2 : (1 / 2 : ℝ) ^ ⌈-logb 2 (p x)⌉₊ = (2 : ℝ) ^ (-(⌈-logb 2 (p x)⌉₊ : ℝ)) := by
      rw [rpow_neg (by norm_num), rpow_natCast, one_div, inv_pow]
    rw [h2]
    calc (2 : ℝ) ^ (-(⌈-logb 2 (p x)⌉₊ : ℝ)) ≤ (2 : ℝ) ^ (logb 2 (p x)) :=
          rpow_le_rpow_of_exponent_le (by norm_num) (by linarith)
      _ = p x := rpow_logb (by norm_num) (by norm_num) (hp x)
  calc ∑ x, (1 / 2 : ℝ) ^ ⌈-logb 2 (p x)⌉₊ ≤ ∑ x, p x := sum_le_sum fun x _ => hterm x
    _ = 1 := hp1
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor
shannon_lengths_boundLean 4Proved here from basic factsFormally verified
/-- **…and they are within one bit of the entropy**: `∑ p(x) ⌈−log₂ p(x)⌉ < H₂(p) + 1`,
where `H₂(p) = ∑ p(x)(−log₂ p(x))` is the entropy in bits (`S` non-empty). Proof:
`⌈t⌉ < t + 1` for `t = −log₂ p(x) ≥ 0`, then average. Together with `source_coding_lower`,
the optimal expected length `L*` satisfies `H₂ ≤ L* < H₂ + 1`. -/
theorem shannon_lengths_bound [Nonempty S] {p : S → ℝ} (hp : ∀ x, 0 < p x)
    (hp1 : ∑ x, p x = 1) :
    ∑ x, p x * ⌈-logb 2 (p x)⌉₊ < ∑ x, p x * (-logb 2 (p x)) + 1 := by
  have hle1 : ∀ x, p x ≤ 1 := fun x => by
    have := single_le_sum (fun y _ => (hp y).le) (mem_univ x)
    rw [hp1] at this
    exact this
  have hterm : ∀ x, p x * ⌈-logb 2 (p x)⌉₊ < p x * (-logb 2 (p x) + 1) := by
    intro x
    have hnn : 0 ≤ -logb 2 (p x) := by
      have := logb_nonpos (by norm_num : (1 : ℝ) < 2) (hp x).le (hle1 x)
      linarith
    exact mul_lt_mul_of_pos_left (Nat.ceil_lt_add_one hnn) (hp x)
  calc ∑ x, p x * ⌈-logb 2 (p x)⌉₊ < ∑ x, p x * (-logb 2 (p x) + 1) :=
        sum_lt_sum_of_nonempty univ_nonempty fun x _ => hterm x
    _ = ∑ x, p x * (-logb 2 (p x)) + 1 := by
        simp only [mul_add, mul_one, sum_add_distrib, hp1]
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

No free compression, by counting:

no_universal_compressionLean 4Proved here from basic factsFormally verified
/-- **No lossless compressor shortens every file.** There is no injective map from the `2ⁿ`
binary strings of length `n` to binary strings of length less than `n` (a string of length
`k < n` is a pair `⟨k, f : Fin k → Bool⟩`). Proof: there are only
`2⁰ + 2¹ + ⋯ + 2ⁿ⁻¹ = 2ⁿ − 1` shorter strings — the pigeonhole principle. -/
theorem no_universal_compression (n : ℕ)
    (f : (Fin n → Bool) → (Σ k : Fin n, (Fin k → Bool))) : ¬ Function.Injective f := by
  intro hf
  have hcard := Fintype.card_le_of_injective f hf
  simp only [Fintype.card_sigma, Fintype.card_fun, Fintype.card_bool, Fintype.card_fin] at hcard
  have hgeom : ∑ k : Fin n, 2 ^ (k : ℕ) = 2 ^ n - 1 := by
    rw [Fin.sum_univ_eq_sum_range (fun k => 2 ^ k) n, Nat.geomSum_eq (le_refl 2)]
    simp
  rw [hgeom] at hcard
  have : 0 < 2 ^ n := pow_pos (by norm_num) n
  omega
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/InformationTheory.leanTry it in the Lean web editor

What is and is not formalised. Proved here: non-negativity of entropy, Gibbs' inequality, H≤log⁡∣X∣H \le \log|\mathcal X|, the capacity of the binary symmetric channel (given the formula for its mutual information), Kraft's inequality (the necessity direction), both source-coding bounds, and the counting argument. Cited from Mathlib: the maximum of the binary entropy. Not formalised: the converse of Kraft (constructing a code from lengths, though Shannon's lengths are shown to satisfy the inequality), conditional entropy, mutual information in general and the data-processing inequality, Huffman's algorithm, the AEP and the coding theorems. Mathlib does not yet contain Shannon's coding theorems.

ComputationC

Codes, typical sets and channels, computed

First, Huffman coding on a real sentence — Article 1 of the Universal Declaration of Human Rights — compared with its entropy, a fixed-length code and Shannon's lengths, and the gain from coding pairs of characters.

Huffman coding and the entropy bound on a real sentencePythonExact computationComputationally tested
"""Huffman coding against the entropy bound, on a real sentence.

We take Article 1 of the Universal Declaration of Human Rights, count its
characters, and treat it as a source emitting characters independently with
those frequencies. We compute the entropy H, build a Huffman code, and check
Kraft's equality and the source coding bounds H <= L < H + 1, compared with a
fixed-length code and with Shannon's lengths ceil(-log2 p). Coding pairs of
characters (under the same independence model) brings the cost per character
closer to H.
"""

import heapq
import math
from collections import Counter
from fractions import Fraction

TEXT = ("All human beings are born free and equal in dignity and rights. They "
        "are endowed with reason and conscience and should act towards one "
        "another in a spirit of brotherhood.")

def frequencies(text):
    """Dictionary symbol -> exact probability (Fraction)."""
    counts = Counter(text)
    total = len(text)
    return {s: Fraction(c, total) for s, c in counts.items()}

def entropy_bits(probs):
    """H = -sum p log2 p, in bits."""
    return -sum(float(p) * math.log2(p) for p in probs.values() if p > 0)

def huffman_lengths(probs):
    """Codeword lengths of a Huffman code for the given probabilities.

    Repeatedly merge the two least likely subtrees; every merge adds one bit
    to the codewords of all symbols inside the two merged subtrees.
    """
    if len(probs) == 1:
        return {s: 1 for s in probs}
    heap = [(p, i, [s]) for i, (s, p) in enumerate(sorted(probs.items(),
                                                          key=str))]
    heapq.heapify(heap)
    lengths = {s: 0 for s in probs}
    counter = len(heap)
    while len(heap) > 1:
        p1, _, group1 = heapq.heappop(heap)
        p2, _, group2 = heapq.heappop(heap)
        for s in group1 + group2:
            lengths[s] += 1
        heapq.heappush(heap, (p1 + p2, counter, group1 + group2))
        counter += 1
    return lengths

def expected_length(probs, lengths):
    """L = sum p(x) l(x), exact."""
    return sum(probs[s] * lengths[s] for s in probs)

def kraft_sum(lengths):
    """sum 2^(-l(x)), exact."""
    return sum(Fraction(1, 2 ** n) for n in lengths.values())

def shannon_lengths(probs):
    """Shannon's lengths ceil(-log2 p(x)), computed exactly for rationals."""
    out = {}
    for s, p in probs.items():
        n = 0
        while Fraction(1, 2 ** n) > p:
            n += 1
        out[s] = n
    return out

def pair_probs(probs):
    """Probabilities of ordered pairs under the independence model."""
    return {(a, b): pa * pb for a, pa in probs.items() for b, pb in probs.items()}

def main():
    probs = frequencies(TEXT)
    k = len(probs)
    h = entropy_bits(probs)
    huff = huffman_lengths(probs)
    shan = shannon_lengths(probs)
    l_huff = expected_length(probs, huff)
    l_shan = expected_length(probs, shan)
    print(f"Text: UDHR Article 1, {len(TEXT)} characters, {k} distinct symbols")
    print(f"  entropy H                    = {h:.4f} bits/char")
    print(f"  fixed-length code            = {math.ceil(math.log2(k))} bits/char")
    print(f"  Shannon code ceil(-log2 p)   = {float(l_shan):.4f} bits/char,"
          f" Kraft sum {float(kraft_sum(shan)):.4f}")
    print(f"  Huffman code                 = {float(l_huff):.4f} bits/char,"
          f" Kraft sum {kraft_sum(huff)}")
    print(f"  H <= L_Huffman < H + 1: {h <= l_huff < h + 1};"
          f" L_Huffman <= L_Shannon: {l_huff <= l_shan}")
    print()
    print("Most and least frequent symbols with their Huffman lengths:")
    ranked = sorted(probs, key=lambda s: (-probs[s], s))
    for s in ranked[:4] + ranked[-2:]:
        name = "space" if s == " " else repr(s)
        print(f"  {name:>7}: p = {str(probs[s]):>7}, length {huff[s]}")
    pairs = pair_probs(probs)
    l_pairs = expected_length(pairs, huffman_lengths(pairs)) / 2
    print()
    print(f"Huffman on pairs (i.i.d. model): {float(l_pairs):.4f} bits/char,"
          f" overhead {float(l_pairs) - h:.4f}")
    print(f"Huffman on single characters:    overhead {float(l_huff) - h:.4f}")
    print()
    print("Epistemic status: exact computation for one sentence and the model")
    print("that draws characters independently with these frequencies. Real")
    print("text has dependence between letters, so its true entropy rate is")
    print("lower than H; the theorems H <= L < H + 1 are proved in the lesson.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Next, the asymptotic equipartition property: for a biased coin, the exact probability and size of the typical set as nn grows.

Typical sequences: the asymptotic equipartition propertyPythonExact computationNumerical approximationComputationally tested
"""The asymptotic equipartition property: few sequences carry almost all probability.

For n independent flips of a coin with P(1) = 0.2, a sequence with k ones has
probability 0.2^k 0.8^(n-k), so -(1/n) log2 p(x) depends only on k. The
typical set T = {x : |-(1/n) log2 p(x) - H| <= eps} can therefore be measured
exactly with binomial coefficients. As n grows, P(T) -> 1 while |T| is only
about 2^(nH) of the 2^n sequences: this is why n H bits suffice to describe
the source.
"""

import math

def h2(p):
    """Binary entropy in bits."""
    return -p * math.log2(p) - (1 - p) * math.log2(1 - p)

def log2_comb(n, k):
    """log2 of the binomial coefficient C(n, k), via lgamma."""
    return (math.lgamma(n + 1) - math.lgamma(k + 1)
            - math.lgamma(n - k + 1)) / math.log(2)

def typical_set(n, p, eps):
    """(P(T), log2 |T|) for the eps-typical set of Bernoulli(p) sequences."""
    h = h2(p)
    prob = 0.0
    log_sizes = []
    for k in range(n + 1):
        rate = -(k * math.log2(p) + (n - k) * math.log2(1 - p)) / n
        if abs(rate - h) <= eps:
            lc = log2_comb(n, k)
            log_sizes.append(lc)
            prob += 2 ** (lc - n * rate)
    if not log_sizes:
        return 0.0, float("-inf")
    top = max(log_sizes)
    log_size = top + math.log2(sum(2 ** (s - top) for s in log_sizes))
    return prob, log_size

def main():
    p, eps = 0.2, 0.05
    h = h2(p)
    print(f"Bernoulli({p}) source: H = {h:.4f} bits per symbol, eps = {eps}")
    print(f"{'n':>6} {'P(typical)':>11} {'log2|T|':>9} {'n H':>8} {'n':>6}"
          f" {'fraction of all':>16}")
    for n in [10, 50, 100, 500, 1000, 2000]:
        prob, log_size = typical_set(n, p, eps)
        print(f"{n:>6} {prob:>11.4f} {log_size:>9.1f} {n * h:>8.1f} {n:>6}"
              f"   2^({log_size - n:.1f})")
    print()
    print("The typical set's probability tends to 1 (law of large numbers).")
    print("Its size is always at most 2^(n(H + eps)), and at least about")
    print("2^(n(H - eps)) once P(T) is near 1, yet it is an exponentially small")
    print("fraction of all 2^n sequences: indexing it needs about n H bits.")
    print()
    print("Epistemic status: exact counts computed in floating-point logarithms")
    print("for six values of n. They illustrate the asymptotic equipartition")
    print("property, which is proved from the weak law of large numbers.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

Finally, channel coding: exact error probabilities of repetition codes and the Hamming code on a binary symmetric channel, a simulation of syndrome decoding, and the capacity for several noise levels.

Repetition codes, the Hamming code and channel capacityPythonExact computationStatistical evidenceComputationally tested
"""Coding over a noisy channel: repetition codes, the Hamming code and capacity.

A binary symmetric channel flips each bit with probability p. Its capacity is
C = 1 - H(p) bits per use. Repetition codes make errors rare only by sending
the rate R = 1/n to zero. The Hamming (7, 4) code sends 4 message bits in 7
channel bits (R = 4/7) and corrects any single flip. We compute exact block
error probabilities, then simulate the Hamming code with syndrome decoding.
"""

import math
import random

#: Generator matrix rows (systematic form): codeword = message . G (mod 2).
G = [[1, 0, 0, 0, 1, 1, 0],
     [0, 1, 0, 0, 1, 0, 1],
     [0, 0, 1, 0, 0, 1, 1],
     [0, 0, 0, 1, 1, 1, 1]]
#: Parity-check matrix: H . codeword = 0 (mod 2) for every codeword.
H = [[1, 1, 0, 1, 1, 0, 0],
     [1, 0, 1, 1, 0, 1, 0],
     [0, 1, 1, 1, 0, 0, 1]]

def h2(p):
    """Binary entropy in bits."""
    if p in (0, 1):
        return 0.0
    return -p * math.log2(p) - (1 - p) * math.log2(1 - p)

def capacity(p):
    """Capacity of the binary symmetric channel, 1 - H(p) bits per use."""
    return 1 - h2(p)

def repetition_error(n, p):
    """Exact error probability of majority decoding for odd n repetitions."""
    if n % 2 == 0:
        raise ValueError("use an odd number of repetitions")
    return sum(math.comb(n, k) * p ** k * (1 - p) ** (n - k)
               for k in range(n // 2 + 1, n + 1))

def hamming_block_error(p):
    """Exact probability that a Hamming (7, 4) block is decoded wrongly.

    Syndrome decoding corrects every pattern of at most one flip and no
    other, so the block is right exactly when at most one bit flips.
    """
    return 1 - (1 - p) ** 7 - 7 * p * (1 - p) ** 6

def encode(message):
    """7-bit codeword of a 4-bit message."""
    return [sum(m * g for m, g in zip(message, col)) % 2 for col in zip(*G)]

def syndrome(word):
    """H . word (mod 2), as a tuple."""
    return tuple(sum(h * w for h, w in zip(row, word)) % 2 for row in H)

def decode(word):
    """Correct at most one flip: the syndrome equals the column of H at the
    flipped position. Return the 4 message bits."""
    s = syndrome(word)
    word = list(word)
    if any(s):
        columns = [tuple(row[j] for row in H) for j in range(7)]
        word[columns.index(s)] ^= 1
    return word[:4]

def simulate_hamming(p, blocks, rng):
    """Fraction of blocks decoded wrongly over a simulated channel."""
    errors = 0
    for _ in range(blocks):
        message = [rng.randrange(2) for _ in range(4)]
        received = [b ^ (rng.random() < p) for b in encode(message)]
        errors += decode(received) != message
    return errors / blocks

def main():
    p = 0.05
    print(f"Binary symmetric channel with p = {p}:"
          f" capacity C = 1 - H(p) = {capacity(p):.4f} bits/use")
    print()
    print("Repetition codes (majority vote):")
    print("    n    rate   error probability")
    for n in [1, 3, 5, 9, 15, 25]:
        print(f"  {n:>3} {1 / n:>7.3f} {repetition_error(n, p):>13.2e}")
    print("Errors vanish only as the rate 1/n goes to 0.")
    print()
    rng = random.Random(1948)
    sim = simulate_hamming(p, 20000, rng)
    print(f"Hamming (7, 4): rate 4/7 = {4 / 7:.3f} < C;"
          f" block error exact {hamming_block_error(p):.4f},"
          f" simulated {sim:.4f}")
    messages = [[(m >> i) & 1 for i in range(4)] for m in range(16)]
    checks = all(not any(syndrome(encode(m))) for m in messages)
    print(f"  all 16 codewords pass the parity checks: {checks}")
    print()
    print("Capacity of the BSC for several p (bits per use):")
    print("  " + "  ".join(f"p={q}: {capacity(q):.3f}"
                           for q in [0.0, 0.01, 0.1, 0.5, 0.9]))
    print()
    print("Epistemic status: the error probabilities and capacities are exact")
    print("formulas evaluated in floating point; the Hamming simulation is")
    print("statistical evidence (standard error about 0.001). That longer codes")
    print("at any fixed rate below C achieve arbitrarily small error is")
    print("Shannon's theorem, which these finite examples do not prove.")

if __name__ == "__main__":
    main()
Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.

The Huffman and typical-set computations are exact (up to floating-point display); the channel experiment combines exact formulas with a statistical simulation. None of them proves the asymptotic theorems; they show their content in concrete cases.

Exercises

Exercises

1. Information theory

Warm-upHuman

A source emits one of 88 symbols, all equally likely. What is its entropy, in bits?

2. Information theory

CoreHuman

A binary prefix code already contains the codewords 00 and 1010. What is the largest number of further codewords of length exactly 33 that can be added while keeping the code prefix-free?

3. Information theory

CoreHuman

Which statements about the mutual information I(X;Y)I(X; Y) of finite random variables are true? (Choose all that apply.)

Choose all that apply

4. Information theory

CoreHuman

In the proof of Gibbs' inequality we bound ∑xp(x)ln⁡q(x)p(x)≤∑x(q(x)−p(x))\sum_x p(x)\ln\frac{q(x)}{p(x)} \le \sum_x \big(q(x) - p(x)\big). Which fact justifies this step?

Choose one

5. Information theory

CoreHuman

Build a Huffman code for four symbols with probabilities 0.4,0.3,0.2,0.10.4, 0.3, 0.2, 0.1. What is the expected codeword length, in tenths of a bit (so 1.51.5 bits would be 1515)?

6. Information theory

CoreHuman

A binary symmetric channel flips each bit independently with probability pp. For which values of pp is its capacity exactly 11 bit per use? (Choose all that apply.)

Choose all that apply

7. Information theory

StretchHuman

A start-up claims its lossless compressor shortens every file of exactly 10001000 bits by at least one bit. What is wrong?

Choose one

8. Information theory

CoreFormal

Which Lean statement formalises Kraft's inequality for prefix codes? (u <+: v means u is a prefix of v.)

Choose one

9. Information theory

StretchComputational

Write entropy(probs) returning −∑plog⁡2p-\sum p\log_2 p in bits (skipping zero probabilities), and kl(p, q) returning D(p ∥ q)=∑plog⁡2(p/q)D(p\,\|\,q) = \sum p\log_2(p/q) (also skipping terms with p=0p = 0). The tests check examples from the lesson, Gibbs' inequality on random distributions, and the asymmetry of relative entropy.

Runs entirely in your browser, in an isolated worker. Nothing is sent to a server.
Common misconceptionsH

Common misconceptions

Misconception

"Information means meaning." Shannon information measures how much uncertainty a message resolves, relative to a probability model of possible messages. A page of random letters has more Shannon information per character than a page of a novel, because it is less predictable; whether a message is true, important or meaningful is outside the theory. The same message can carry different amounts of information to receivers with different models.

Misconception

"A clever enough compression method can shrink every file." There are 2n2^n files of nn bits but only 2n−12^n - 1 shorter files, so any lossless compressor that shortens some files must lengthen others (formalised above). Compressors work because real data are far from uniformly random; on random data they cannot gain on average, by the source coding theorem.

Misconception

"Entropy is a property of a single message." Entropy is a property of a probability distribution — of a source — not of one string. The string 0101010101 is neither high- nor low-entropy by itself; it is very probable under one model and improbable under another. (The algorithmic notion of complexity of an individual string is Kolmogorov complexity; see the viewpoints.)

Misconception

"Relative entropy is a distance." D(p ∥ q)≥0D(p \,\|\, q) \ge 0 with equality only for p=qp = q, but it is not symmetric and does not satisfy the triangle inequality: for p=(12,12)p = (\tfrac12, \tfrac12) and q=(14,34)q = (\tfrac14, \tfrac34), D(p∥q)≈0.208D(p\|q) \approx 0.208 bits but D(q∥p)≈0.189D(q\|p) \approx 0.189 bits, and D(p∥q)D(p\|q) is infinite if qq rules out something pp allows.

Misconception

"More noise always means lower capacity." A binary channel that flips every bit (p=1p = 1) has capacity 11: the receiver flips them back. Capacity measures how much the output reveals about the input; it is smallest, zero, at p=12p = \frac12, where output and input are independent.

ViewpointsH

Many ways of seeing

Physics— Entropy in thermodynamics, and the cost of erasing a bit

Shannon's formula is Gibbs's entropy S=−kB∑ipiln⁡piS = -k_B\sum_i p_i\ln p_i of statistical mechanics (with Boltzmann's S=kBln⁡WS = k_B\ln W for WW equally likely microstates), and von Neumann reportedly advised Shannon to call his quantity entropy. The connection is more than notation. Leo Szilard (1929) analysed Maxwell's demon with a one-molecule engine and argued that acquiring one bit of information has a thermodynamic cost; Rolf Landauer (1961) located the cost in erasure: resetting a bit in an environment at temperature TT dissipates at least kBTln⁡2k_BT\ln 2 of heat, and Charles Bennett (1982) used this to exorcise the demon. Landauer's bound has since been approached experimentally. Maximum-entropy reasoning (Jaynes, 1957) derives the Boltzmann distribution as the distribution of largest entropy with a given mean energy. These are physical claims resting on physical models, not theorems of the mathematics above. See quantum mechanics for von Neumann's quantum entropy.

Geometry— Information geometry and packing spheres

Relative entropy behaves like a squared distance without being one. Infinitesimally it is: for a smooth family pθp_\theta, D(pθ ∥ pθ+dθ)≈12 dθ⊤I(θ) dθD(p_\theta \,\|\, p_{\theta + d\theta}) \approx \frac12\,d\theta^\top I(\theta)\,d\theta, where I(θ)I(\theta) is the Fisher information matrix — a Riemannian metric on the space of distributions, the starting point of information geometry (Rao, 1945; Chentsov; Amari). Relative entropy also obeys a Pythagorean theorem: if p∗p^* minimises D(p ∥ q)D(p \,\|\, q) over a convex set EE of distributions, then D(p ∥ q)≥D(p ∥ p∗)+D(p∗ ∥ q)D(p \,\|\, q) \ge D(p \,\|\, p^*) + D(p^* \,\|\, q) for all p∈Ep \in E (Csiszár, 1975). Channel coding has a geometric picture too: codewords are points of the Hamming cube {0,1}n\{0, 1\}^n, noise moves a codeword to a random point at distance about pnpn, and decoding works if the "noise balls" around codewords do not overlap. Each ball holds about 2nH2(p)2^{nH_2(p)} points, so at most 2n/2nH2(p)=2n(1−H2(p))2^n/2^{nH_2(p)} = 2^{n(1 - H_2(p))} codewords fit — the capacity, as a sphere-packing bound. See smooth manifolds.

Combinatorics— Counting sequences: the method of types

Entropy is the exponent of a binomial coefficient: (nk)=2nH2(k/n)+O(log⁡n)\binom{n}{k} = 2^{nH_2(k/n) + O(\log n)}, and more generally the number of sequences of length nn with a given type (empirical distribution) qq is 2nH(q)+O(log⁡n)2^{nH(q) + O(\log n)}, while each such sequence has probability 2−n(H(q)+D(q∥p))2^{-n(H(q) + D(q\|p))} under an i.i.d. source pp. Multiplying, the probability of seeing type qq is 2−nD(q∥p)+O(log⁡n)2^{-nD(q\|p) + O(\log n)} — Sanov's theorem, the basic result of large deviations. The source and channel coding theorems can be proved entirely by this counting (Csiszár and Körner). Entropy also gives combinatorial inequalities: Shearer's lemma, ∑iH(XSi)≥k H(X)\sum_i H(X_{S_i}) \ge k\,H(X) when every coordinate lies in at least kk of the sets SiS_i, bounds the number of triangles in a graph with a given number of edges and proves the Loomis–Whitney inequality. See enumerative combinatorics.

Computation— Kolmogorov complexity: information of a single string

Shannon entropy belongs to sources. Kolmogorov (1965), Solomonoff (1964) and Chaitin (1966) defined the information content of an individual string xx as the length K(x)K(x) of the shortest program that prints it, on a fixed universal machine (changing the machine changes KK by at most a constant). Most strings are incompressible: fewer than 2n−c2^{n - c} programs are shorter than n−cn - c bits, the same counting as above. For a computable i.i.d. source, E[K(X1…Xn)]/n→HE[K(X_1 \dots X_n)]/n \to H, so the two notions agree on average. But KK is not computable: a program computing it could search for the first string of complexity above NN and print it, using only about log⁡N\log N bits — a version of Berry's paradox. Practical compressors (Lempel–Ziv, 1977–78, which underlies ZIP and PNG) are universal: for every stationary ergodic source their compression rate tends to the entropy rate. See computability and, for the use of entropy in secrecy, cryptography.

Probability— Entropy along Markov chains

For a stationary Markov chain with transition matrix PP and stationary distribution π\pi, the entropy rate lim⁡nH(X1,…,Xn)/n\lim_n H(X_1, \dots, X_n)/n is −∑iπi∑jpijlog⁡pij-\sum_i \pi_i\sum_j p_{ij}\log p_{ij}, the average uncertainty of the next step; a source with memory is more compressible than its single-letter frequencies suggest, as Shannon's English experiments showed. Information also measures convergence: for any initial distribution λ\lambda, the relative entropy D(λPn ∥ π)D(\lambda P^n \,\|\, \pi) is non-increasing in nn (a consequence of the data-processing inequality for relative entropy) — a "second law" for Markov chains. And in statistics, maximum likelihood is minimum relative entropy: maximising the average log-likelihood over a model is minimising D(p^ ∥ pθ)D(\hat p \,\|\, p_\theta) from the empirical distribution p^\hat p.

History & global context

History and global context

  • Before Shannon. Telegraph engineers knew that frequent letters deserve short codes: Alfred Vail and Samuel Morse's code (1830s–40s) gave E a single dot. Harry Nyquist (1924) and Ralph Hartley (1928) at Bell Laboratories measured information by the logarithm of the number of possible messages.
  • 1948. Claude Shannon's A Mathematical Theory of Communication introduced entropy, mutual information and capacity, and stated and sketched proofs of the source and channel coding theorems. Norbert Wiener's Cybernetics appeared the same year with related ideas. Leon Kraft's inequality (1949) and Robert Fano's coding method followed, and David Huffman found his optimal algorithm in 1952 as a student in Fano's course at MIT.
  • Rigour and codes. Aleksandr Khinchin (1953) and Amiel Feinstein (1954) gave rigorous proofs of Shannon's theorems, and Jacob Wolfowitz (1957) proved the strong converse; Solomon Kullback and Richard Leibler introduced their divergence in 1951; Brockway McMillan's inequality dates from 1956. Richard Hamming (1950) and Marcel Golay (1949) built the first error-correcting codes, Irving Reed and Gustave Solomon theirs in 1960, and Robert Gallager his low-density parity-check codes in 1962.
  • Computation and capacity-achieving codes. Andrei Kolmogorov (1965), Ray Solomonoff (1964) and Gregory Chaitin (1966) founded algorithmic information theory; Abraham Lempel and Jacob Ziv's compression algorithms (1977–78) are used in everyday file formats; Richard Blahut and Suguru Arimoto (1972) gave an algorithm for computing capacity. Claude Berrou, Alain Glavieux and Punya Thitimajshima's turbo codes (1993) and Erdal Arıkan's polar codes (2009) finally approached Shannon's limit in practice.
Further reading

Further reading

  • Thomas M. Cover and Joy A. Thomas, Elements of Information Theory (1991; 2nd edition 2006) — the standard text, with complete proofs of the coding theorems.
  • David J. C. MacKay, Information Theory, Inference, and Learning Algorithms (2003) — information theory together with coding, Bayesian inference and neural networks, full of exercises.
  • Claude E. Shannon and Warren Weaver, The Mathematical Theory of Communication (1949) — Shannon's paper, still very readable, with Weaver's essay on its broader meaning.
  • Imre Csiszár and János Körner, Information Theory: Coding Theorems for Discrete Memoryless Systems (1981; 2nd edition 2011) — the method of types.
  • Ming Li and Paul Vitányi, An Introduction to Kolmogorov Complexity and Its Applications (1993; 4th edition 2019).
  • Robert M. Gray, Entropy and Information Theory (1990; 2nd edition 2011) — the measure-theoretic foundations.