Skip to content
The Lumenary
Advanced undergraduateUndergraduate 110 min

Knot theory

How do you prove that a tangle cannot be untied — or that a knot differs from its mirror image? With diagrams, three local moves, and invariants that the moves cannot change.

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

Can it be untied?

People have tied knots for as long as there have been ropes. In the Andes, Inca administrators kept census and tax records in khipu, cords whose knot types and positions encoded numbers. Chinese decorative knotting, Celtic interlace and Islamic geometric strapwork turned knots into art, and sailors everywhere developed knots for every task. Inside our cells, enzymes called topoisomerases cut and reseal DNA to undo the knots and links that form when long molecules are copied and packed. Biologists identify the products under the electron microscope by their knot type.

The mathematical question is older than it looks and harder than it sounds. Take a piece of string, tie it in a tangle, and fuse the two ends, so that it can no longer slip off. Is the result really knotted? That is, is there any way to move it around in space, without cutting, so that it becomes a plain round loop? For the simplest knot, the trefoil, everyone is sure the answer is no — but sure is not proof. Wiggling the string for an hour and failing to untie it proves nothing about the next hour. A proof needs a quantity that every allowed motion preserves, and that differs between the trefoil and the plain loop.

A second question is subtler. The trefoil comes in a left-handed and a right-handed version, mirror images of each other. Can one be turned into the other? Max Dehn proved in 1914 that it cannot. This lesson proves both facts, using diagrams, three local moves, and three generations of invariants: colourings (1950s), linking numbers (Gauss, 1833) and the Jones polynomial (1984).

IntuitionH

Pictures of knots, and moves between them

A knot lives in three-dimensional space, but we draw it on paper: a closed curve with crossings, where a small gap in one strand shows that it passes under the other. The same knot has infinitely many diagrams. A round circle and a figure-eight-shaped loop with one crossing are both the unknot. So we need to know when two diagrams show the same knot.

Kurt Reidemeister's answer (1927) is that three local moves suffice:

  • Move I puts in or takes out a kink: a small loop with one crossing.
  • Move II slides one strand over another, creating or removing two crossings.
  • Move III slides a strand over a crossing of two other strands.

Two diagrams show the same knot exactly when one can be turned into the other by these moves (and by wiggling the drawing without changing its crossings). So to prove that two knots are different, it is enough to find a quantity, computed from a diagram, that none of the three moves can change, and that takes different values on the two diagrams. Such a quantity is a knot invariant. Each invariant in this lesson is proved invariant by checking three small pictures.

↔I↔II↔III
The three Reidemeister moves, each a change inside a small disc; outside the disc the diagram is untouched. I: a kink appears or disappears. II: one strand slides across another, creating two crossings. III: a strand slides across a crossing of two other strands, passing over both.
DefinitionsH

Knots, diagrams and invariants

Definition— knot, link, equivalence

A knot is a smooth embedding K:S1→R3K : S^1 \to \R^3 (or into S3=R3∪{∞}S^3 = \R^3 \cup \{\infty\}); a link with mm components is a smooth embedding of mm disjoint circles. Two knots or links are equivalent if there is an ambient isotopy between them: a continuous family of homeomorphisms ht:R3→R3h_t : \R^3 \to \R^3, t∈[0,1]t \in [0, 1], with h0=idh_0 = \mathrm{id} and h1h_1 carrying the first onto the second. The unknot is the round circle; a knot equivalent to it is unknotted.

Requiring smoothness (or, equivalently for our purposes, that knots be polygonal — tame) excludes wild knots, with infinitely many smaller and smaller knots tied in them. For wild knots, the theory below fails.

Definition— diagram, Reidemeister moves

A diagram of a knot is a projection to a plane that is injective except at finitely many transverse double points, the crossings, each marked with which strand passes over. Every tame knot has diagrams. The arcs of a diagram are the unbroken strands between undercrossings. The Reidemeister moves I, II, III are the local changes pictured above.

Definition— knot invariant

A knot invariant is a function on knots that takes equal values on equivalent knots. In practice it is computed from a diagram and proved to be unchanged by the three Reidemeister moves. The crossing number c(K)c(K), the least number of crossings in any diagram of KK, is an invariant by definition — but it is hard to compute, since one must know about all diagrams.

Definition— Fox colouring, tricolourability

Let p≥3p \ge 3 be an integer. A Fox pp-colouring of a diagram assigns to each arc a colour in Z/p\Z/p such that at every crossing, with over-arc coloured xx and under-arcs coloured y,zy, z,

2x≡y+z(modp).2x \equiv y + z \pmod p .

Constant colourings always work. A diagram is tricolourable if it has a 33-colouring using at least two colours. Since 2≡−1(mod3)2 \equiv -1 \pmod 3, the condition 2x≡y+z2x \equiv y + z says x+y+z≡0x + y + z \equiv 0: the three colours at a crossing are all equal or all different.

Definition— crossing sign, writhe, linking number

For an oriented diagram, a crossing is positive (right-handed) if, looking along the over-strand, the under-strand passes from right to left, and negative otherwise. The writhe w(D)w(D) is the sum of the signs of all crossings. For a two-component oriented link, the linking number lk(L1,L2)\mathrm{lk}(L_1, L_2) is half the sum of the signs of the crossings between the two components.

Definition— Kauffman bracket, Jones polynomial

The Kauffman bracket ⟨D⟩∈Z[A,A−1]\langle D\rangle \in \Z[A, A^{-1}] of an unoriented diagram is defined by three rules: ⟨O⟩=1\langle O\rangle = 1 for the round circle; ⟨D⊔O⟩=δ⟨D⟩\langle D \sqcup O\rangle = \delta \langle D\rangle with δ=−A2−A−2\delta = -A^2 - A^{-2}; and at any crossing,

⟨D⟩=A ⟨DA⟩+A−1⟨DB⟩,\langle D \rangle = A\,\langle D_A \rangle + A^{-1} \langle D_B \rangle ,

where DAD_A and DBD_B are the diagrams with that crossing smoothed in the two possible ways. The A-smoothing opens a channel between the two regions swept out when the over-strand is turned anticlockwise; the B-smoothing joins the other two. Expanding every crossing gives the state sum

⟨D⟩=∑states SAa(S)−b(S) δ ∣S∣−1,\langle D \rangle = \sum_{\text{states } S} A^{a(S) - b(S)} \, \delta^{\,|S| - 1},

over the 2n2^n choices of smoothings, where a(S),b(S)a(S), b(S) count the A- and B-smoothings and ∣S∣|S| is the number of resulting circles. For an oriented knot diagram, f(D)=(−A3)−w(D)⟨D⟩f(D) = (-A^3)^{-w(D)} \langle D \rangle, and the Jones polynomial is VK(t)=f(D)V_K(t) = f(D) with A=t−1/4A = t^{-1/4}.

Definition— Seifert surface, genus

A Seifert surface for a knot KK is a compact, connected, orientable surface Σ⊂R3\Sigma \subset \R^3 with boundary ∂Σ=K\partial \Sigma = K. The genus g(K)g(K) is the least genus of a Seifert surface for KK.

Worked examplesH

A small zoo

Example— Knots

The trefoil 313_1 has a diagram with 33 crossings and 33 arcs, each passing over once; it comes in a right-handed and a left-handed form. The figure-eight knot 414_1 has a 44-crossing diagram. In the standard tables (Alexander–Briggs, Rolfsen), knots are named by crossing number and position, so 515_1 and 525_2 are the two knots with crossing number 55. Mirror images are not listed separately. Up to 1616 crossings there are 1,701,9361{,}701{,}936 prime knots (Hoste, Thistlethwaite and Weeks, 1998).

Example— Links

The Hopf link consists of two circles linked once; its standard diagram has two crossings, both between the components. The Whitehead link has five crossings, four of them between the components, with signs +1,−1,+1,−1+1, -1, +1, -1, so its linking number is 00 — yet it cannot be pulled apart. The Borromean rings are three circles, no two of which are linked (pairwise linking numbers 00, and any two of them alone can be separated), but the three together cannot be separated.

Example— A tricolouring of the trefoil

Colour the three arcs of the trefoil 0,1,20, 1, 2. At each crossing the three arcs carry all three colours, and 0+1+2=3≡0(mod3)0 + 1 + 2 = 3 \equiv 0 \pmod 3. So the trefoil diagram is tricolourable. The round unknot diagram has one arc, so it is not. In total the trefoil diagram has 99 tricolourings: 33 constant and 66 using all three colours (the colours of two arcs can be chosen freely, 3×3=93 \times 3 = 9, and the third is forced).

Example— The bracket of the trefoil, state by state

For the standard right-handed trefoil diagram, the 88 states give ∣S∣=2|S| = 2 circles for AAA, 11 circle for each state with two A's, 22 circles for each state with one A, and 33 circles for BBB. So

⟨31⟩=A3δ+3A+3A−1δ+A−3δ2=−A5−A−3+A−7.\langle 3_1 \rangle = A^3 \delta + 3A + 3A^{-1}\delta + A^{-3}\delta^2 = -A^5 - A^{-3} + A^{-7}.

All 33 crossings are positive, so w=3w = 3 and f=(−A3)−3⟨31⟩=−A−16+A−12+A−4f = (-A^3)^{-3}\langle 3_1\rangle = -A^{-16} + A^{-12} + A^{-4}. With A=t−1/4A = t^{-1/4}:

V31(t)=t+t3−t4.V_{3_1}(t) = t + t^3 - t^4 .

The same computation is carried out by the Lean file and the Python experiment below.

ProofH

Reidemeister's theorem and colourings

Theorem— Theorem 1 (Reidemeister 1927; Alexander and Briggs 1926 — proof referenced)

Two diagrams represent equivalent tame knots (or links) if and only if they are related by a finite sequence of Reidemeister moves and planar isotopies.

Proof sketch. One direction is clear: each move is realised by an isotopy in a neighbourhood of the small disc where it happens. For the other, replace the knots by polygons, and the isotopy by a sequence of triangle moves, each replacing one edge of the polygon by the other two sides of a triangle that meets the knot only in that edge (or the reverse). After a small perturbation into general position, the projection of each triangle move can be decomposed into Reidemeister moves. See Burde and Zieschang, Knots, chapter 1, or Lickorish (1997), chapter 1.

Theorem— Theorem 2 (Fox colourings are invariants)

For every pp, the number of Fox pp-colourings of a diagram is unchanged by Reidemeister moves. Hence it is a knot invariant, and so is tricolourability.

Proof

A move changes the diagram only inside a small disc. We show that colourings of the diagram before and after correspond one to one, agreeing outside the disc. It suffices to show that the colours of the arcs leaving the disc determine those inside, and that the constraints on the outside colours are the same before and after. Write x▹y=2x−yx \triangleright y = 2x - y for the colour of an under-arc yy after it passes under an arc of colour xx.

Move I. At a kink the over-arc is also one of the two under-arcs: if it has colour aa and the other under-arc colour bb, the rule says 2a=a+b2a = a + b, i.e. b=ab = a. So the strand keeps one colour through the kink, exactly as if there were no kink.

Move II. A strand of colour xx passes over a strand that is cut into three arcs a,m,ba, m, b. The two crossings say 2x=a+m2x = a + m and 2x=m+b2x = m + b, which hold exactly when m=2x−am = 2x - a and b=ab = a. So the middle colour is forced, and the outgoing colour equals the incoming one, as without the move.

Move III. Let the incoming colours be tt (top strand), mm (middle) and bb (bottom). The top strand stays tt on both sides. The middle strand passes under the top one on both sides and leaves with colour t▹mt \triangleright m. The bottom strand passes under both. On one side it goes under the middle strand first, then under the top: it leaves with t▹(m▹b)t \triangleright (m \triangleright b). On the other side it goes under the top first, then under the middle strand, whose colour there is already t▹mt \triangleright m: it leaves with (t▹m)▹(t▹b)(t \triangleright m) \triangleright (t \triangleright b). These agree:

2t−(2m−b)=2(2t−m)−(2t−b),2t - (2m - b) = 2(2t - m) - (2t - b),

as both sides equal 2t−2m+b2t - 2m + b. The interior colours are again forced.

So the colourings correspond bijectively, and their number is unchanged. A colouring uses at least two colours exactly when its counterpart does, since the colours on the boundary of the disc (and outside it) are the same.

∎

The identity in move III, x▹(y▹z)=(x▹y)▹(x▹z)x \triangleright (y \triangleright z) = (x \triangleright y) \triangleright (x \triangleright z), is self-distributivity. Together with x▹x=xx \triangleright x = x (move I) and the invertibility of y↦x▹yy \mapsto x \triangleright y (move II), it makes Z/p\Z/p a quandle — the dihedral quandle.

Theorem— Corollary 3

(a) The trefoil is knotted. (b) The figure-eight knot is knotted. (c) The trefoil and the figure-eight knot are different.

Proof

Count colourings (all counts are formalised in Lean below). The unknot's round diagram has one arc, so it has exactly pp colourings for every pp. The trefoil diagram has 99 three-colourings, while the unknot has 33; this proves (a). The figure-eight diagram has only the 33 constant three-colourings, so it is not tricolourable — that alone proves nothing! But it has 2525 five-colourings, against 55 for the unknot, which proves (b). The trefoil has only 55 five-colourings and 99 three-colourings, versus 2525 and 33 for the figure-eight knot, which proves (c).

∎

More generally, the number of pp-colourings, for pp prime, is p1+kp^{1 + k}, where kk is the dimension of the kernel of the reduced colouring matrix mod pp. A non-constant pp-colouring exists exactly when pp divides the determinant of the knot, ∣ΔK(−1)∣|\Delta_K(-1)|, where ΔK\Delta_K is the Alexander polynomial. The determinants of 31,41,51,52,613_1, 4_1, 5_1, 5_2, 6_1 are 3,5,5,7,93, 5, 5, 7, 9 (see the computation section).

ProofH

The linking number

Theorem— Theorem 4 (the linking number is an invariant)

The linking number of an oriented two-component link is an integer and is unchanged by Reidemeister moves.

Proof

For a two-component diagram, let s1s_1 be the sum of the signs of the crossings where L1L_1 passes over L2L_2, and s2s_2 the sum over the crossings where L1L_1 passes under L2L_2, so that lk=12(s1+s2)\mathrm{lk} = \tfrac12 (s_1 + s_2).

Invariance of s1s_1 and s2s_2. Move I creates a crossing of a component with itself, which does not count. Move II creates two crossings between the same two strands, with the same strand on top and opposite signs; if the strands belong to different components, both crossings fall into the same sum, s1s_1 or s2s_2, and cancel. Move III moves strands past a crossing without changing any crossing's sign, or which strand is on top. So s1s_1, s2s_2 and lk\mathrm{lk} are invariant.

lk\mathrm{lk} is an integer. We show s1=s2s_1 = s_2. Switching a crossing between the components (exchanging over and under) reverses its sign and moves it from one sum to the other, so it leaves s1−s2s_1 - s_2 unchanged. Switch every crossing where L1L_1 passes under L2L_2. In the resulting diagram L1L_1 is on top at every crossing between the components, so we can lift L1L_1 into a horizontal slab above L2L_2 and slide it sideways. The result is a diagram with no crossings between the components, where s1=s2=0s_1 = s_2 = 0. By invariance s1=s2=0s_1 = s_2 = 0 in the switched diagram too, so there s1−s2=0s_1 - s_2 = 0, and therefore s1=s2s_1 = s_2 in the original diagram. Hence lk=s1\mathrm{lk} = s_1 is an integer.

∎

The Hopf link has two crossings between its components, both of sign +1+1 (for one choice of orientations), so lk=1≠0\mathrm{lk} = 1 \ne 0: it cannot be pulled apart. The Whitehead link has lk=0\mathrm{lk} = 0 but is still linked, and the Borromean rings have all pairwise linking numbers 00. The linking number is a useful but incomplete invariant. Gauss found it in 1833 as an integral over the two curves, lk=14π∮∮(r1−r2)⋅(dr1×dr2)∣r1−r2∣3\mathrm{lk} = \frac{1}{4\pi} \oint\oint \frac{(\mathbf{r}_1 - \mathbf{r}_2) \cdot (d\mathbf{r}_1 \times d\mathbf{r}_2)}{|\mathbf{r}_1 - \mathbf{r}_2|^3}, while studying the orbits of asteroids and electromagnetism.

ProofH

The Kauffman bracket and the Jones polynomial

Theorem— Theorem 5 (Kauffman 1987)

(a) The bracket ⟨D⟩\langle D\rangle is unchanged by moves II and III. (b) Move I multiplies it by −A3-A^{3} or −A−3-A^{-3}, according to the sign of the kink. (c) Consequently f(D)=(−A3)−w(D)⟨D⟩f(D) = (-A^3)^{-w(D)}\langle D\rangle is an invariant of oriented knots, and so is the Jones polynomial VK(t)V_K(t).

Proof

(a) Move II. Expand both crossings of the two-crossing tangle with the bracket rule. The two states that smooth both crossings the same way contribute A2A^2 and A−2A^{-2} times the bracket of the "cup–cap" tangle ≍\asymp. Of the two mixed states (each with coefficient A⋅A−1=1A \cdot A^{-1} = 1), one gives two parallel strands, the tangle after the move, and the other gives ≍\asymp with an extra small circle, contributing δ\delta times the cup–cap bracket. In total

⟨II-tangle⟩=(A2+A−2+δ) ⟨≍⟩+⟨parallel strands⟩=⟨parallel strands⟩,\langle \text{II-tangle} \rangle = (A^2 + A^{-2} + \delta)\,\langle \asymp \rangle + \langle \text{parallel strands} \rangle = \langle \text{parallel strands} \rangle ,

because δ=−A2−A−2\delta = -A^2 - A^{-2}. This is why δ\delta must have that value.

Move III. Expand the crossing between the two lower strands (the one the moving strand does not touch) on both sides of the move. The two A-smoothings give tangles related by two moves II, and so do the two B-smoothings. By the case just proved their brackets agree, hence so do the brackets before and after move III.

(b) Move I. Smoothing the crossing of a kink one way leaves the strand plus a small circle, and the other way leaves just the strand. For a positive kink (with the conventions above) the A-smoothing produces the circle:

⟨kink⟩=A δ ⟨∣⟩+A−1⟨∣⟩=(−A3−A−1+A−1)⟨∣⟩=−A3⟨∣⟩.\langle \text{kink} \rangle = A\,\delta\,\langle | \rangle + A^{-1}\langle | \rangle = (-A^3 - A^{-1} + A^{-1})\langle | \rangle = -A^3 \langle | \rangle .

For a negative kink the roles of the smoothings swap, giving A+A−1δ=−A−3A + A^{-1}\delta = -A^{-3}.

(c) Moves II and III do not change the writhe (move II adds one positive and one negative crossing; move III preserves the signs). Move I changes ww by ±1\pm 1 and ⟨D⟩\langle D \rangle by −A±3-A^{\pm 3}, and these cancel in f(D)f(D). For a knot, the exponents of AA in f(D)f(D) are multiples of 44, so the substitution A=t−1/4A = t^{-1/4} gives a Laurent polynomial in tt.

∎

Theorem— Corollary 6 (the trefoil is chiral; Dehn 1914)

The right-handed trefoil is not equivalent to its mirror image.

Proof

Reflecting a diagram switches every crossing. That exchanges A- and B-smoothings, so ⟨Dˉ⟩(A)=⟨D⟩(A−1)\langle \bar D\rangle(A) = \langle D\rangle(A^{-1}), and it negates every crossing sign, so w(Dˉ)=−w(D)w(\bar D) = -w(D). Hence VKˉ(t)=VK(t−1)V_{\bar K}(t) = V_K(t^{-1}). For the trefoil, V(t)=t+t3−t4V(t) = t + t^3 - t^4, while its mirror has V(t)=t−1+t−3−t−4V(t) = t^{-1} + t^{-3} - t^{-4}. These differ, and VV is an invariant (Theorem 5), so the two knots are not equivalent.

∎

The figure-eight knot has V(t)=t−2−t−1+1−t+t2=V(t−1)V(t) = t^{-2} - t^{-1} + 1 - t + t^2 = V(t^{-1}), consistent with the fact that it is equivalent to its mirror image (it is amphichiral; one sees this by an explicit isotopy). The symmetry of VV alone would not prove this: the knot 9429_{42} is chiral but its Jones polynomial is symmetric.

Dehn's original proof (1914) used the fundamental group of the knot complement. The Jones polynomial, discovered by Vaughan Jones in 1984, made the result a short computation.

ProofH

Seifert surfaces and genus

Theorem— Theorem 7 (Seifert 1934)

Every knot bounds a Seifert surface. If a diagram of KK with cc crossings produces ss Seifert circles (see the proof), the resulting surface has genus 12(c−s+1)\tfrac12(c - s + 1).

Proof

Seifert's algorithm. Orient the knot and take a diagram. At each crossing, smooth in the way that respects the orientation: the two incoming strands are joined to the two outgoing ones without reversing direction. The result is a family of disjoint oriented circles in the plane, the Seifert circles. Fill each with a disc, placing nested discs at different heights. At each former crossing, attach a half-twisted band joining the two discs there, twisted according to the crossing. The boundary of this surface is the knot.

The surface is orientable: give each disc the orientation from its circle (anticlockwise discs face up, clockwise ones down); the half-twisted bands join discs consistently, because the smoothing respected the orientation. It is connected if the diagram is connected. It deformation retracts onto a graph with ss vertices (the discs) and cc edges (the bands), so its Euler characteristic is χ=s−c\chi = s - c. A compact connected orientable surface of genus gg with one boundary circle has χ=2−2g−1=1−2g\chi = 2 - 2g - 1 = 1 - 2g. So g=12(1−s+c)g = \tfrac12(1 - s + c).

∎

×××inner discouter disc
Seifert's algorithm on the standard trefoil diagram: smoothing the 3 crossings along the orientation gives 2 nested Seifert circles; the discs they bound are joined by 3 half-twisted bands. Then χ = 2 − 3 = −1 = 1 − 2g, so the surface has genus 1 — a punctured torus.

So the trefoil has genus at most 11, and since it is knotted its genus is not 00 (a knot of genus 00 bounds an embedded disc, and so is unknotted). Hence g(31)=1g(3_1) = 1. Two further theorems, which we only state: the genus is additive under connected sum, g(K1#K2)=g(K1)+g(K2)g(K_1 \# K_2) = g(K_1) + g(K_2) (Schubert, 1949). In particular no knot can be cancelled by tying another knot in the same string. And every knot decomposes uniquely into prime knots (Schubert, 1949).

ExplanationH

What is known, and what is open

Known. Knots are classified algorithmically: Wolfgang Haken (1961) gave an algorithm to decide whether a knot is unknotted, using normal surfaces, and later work (building on Haken, Thurston's geometrisation and the work of many others) gives an algorithm to decide whether any two knots are equivalent. Unknot recognition is in the complexity class NP (Hass, Lagarias and Pippenger, 1999) and in co-NP (Lackenby). Any diagram of the unknot with cc crossings can be untangled with at most (236c)11(236c)^{11} Reidemeister moves (Lackenby, 2015). Knots are determined by their complements, up to mirror image and orientation (Gordon and Luecke, 1989). Khovanov homology, a refinement of the Jones polynomial, detects the unknot (Kronheimer and Mrowka, 2011).

Open. Does the Jones polynomial detect the unknot — is there a non-trivial knot KK with VK(t)=1V_K(t) = 1? This is unknown, although the answer is known to be no for knots with few crossings, which have been checked by computer, and there are non-trivial links with the Jones polynomial of an unlink (Eliahou, Kauffman and Thistlethwaite, 2003). Also open: whether unknot recognition can be done in polynomial time (Marc Lackenby has announced a quasi-polynomial-time algorithm), and the slice–ribbon conjecture of Ralph Fox (1962): is every smoothly slice knot — one bounding a smooth disc in the four-ball — a ribbon knot? Such questions lie at the frontier of low-dimensional topology.

Formal mathematicsF

Knot diagrams in Lean

Mathlib does not (yet) contain knots as embeddings of the circle, ambient isotopy, or Reidemeister's theorem. So the Lean module works with diagram codes, finite data that Lean can compute with, and proves the algebra and the computations. It does not prove the topological step "a diagram invariant is a knot invariant"; that is Theorem 1 together with the invariance proofs above.

A diagram is a list of arcs and crossings, and a Fox colouring is a function on arcs satisfying 2x=y+z2x = y + z at every crossing:

ArcDiagramLean 4Formally verified
/-- A knot diagram, recorded by its **arcs** (the unbroken strands, numbered `0, …, arcs - 1`) and
its **crossings**. A crossing `(o, u₁, u₂)` lists the arc `o` passing over and the two arcs `u₁`,
`u₂` that end there, passing under. -/
structure ArcDiagram where
  arcs : ℕ
  crossings : List (Fin arcs × Fin arcs × Fin arcs)
Axioms used: No axiomsformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
IsFoxColouringLean 4Formally verified
/-- A **Fox `p`-colouring** gives each arc a colour in `ZMod p` so that at every crossing
`2 · (over) = (under₁) + (under₂)`. For `p = 3` this says the three colours at a crossing are
all equal or all different — the tricolouring rule. -/
def IsFoxColouring (D : ArcDiagram) (p : ℕ) (c : Fin D.arcs → ZMod p) : Prop :=
  ∀ x ∈ D.crossings, 2 * c x.1 = c x.2.1 + c x.2.2
Axioms used: propext, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
trefoilDiagramLean 4Formally verified
/-- The standard trefoil diagram: three arcs and three crossings, each arc passing over once. -/
abbrev trefoilDiagram : ArcDiagram := ⟨3, [(0, 1, 2), (1, 2, 0), (2, 0, 1)]⟩
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
figureEightDiagramLean 4Formally verified
/-- The standard figure-eight diagram: four arcs `0 = A, 1 = B, 2 = C, 3 = D` and four crossings
(over; under, under) = (A; B, C), (C; D, A), (B; C, D), (D; A, B). -/
abbrev figureEightDiagram : ArcDiagram := ⟨4, [(0, 1, 2), (2, 3, 0), (1, 2, 3), (3, 0, 1)]⟩
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

Tricolourability of the trefoil and its failure for the unknot, and the colouring counts used in Corollary 3, verified by checking all 333^3, 343^4, 535^3 and 545^4 colourings with decide:

trefoil_tricolourableLean 4Proved here from basic factsFormally verified
/-- **The trefoil diagram is tricolourable**: colour its arcs `0, 1, 2`. At each crossing the
three colours are all different, and `2 · 0 = 1 + 2`, `2 · 1 = 2 + 0`, `2 · 2 = 0 + 1` in
`ZMod 3`. -/
theorem trefoil_tricolourable :
    ∃ c : Fin 3 → ZMod 3, IsFoxColouring trefoilDiagram 3 c ∧ ∃ i j, c i ≠ c j :=
  ⟨![0, 1, 2], by decide, 0, 1, by decide⟩
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
unknot_not_tricolourableLean 4Proved here from basic factsFormally verified
/-- **The round unknot diagram is not tricolourable**: it has one arc, so any colouring uses one
colour. -/
theorem unknot_not_tricolourable :
    ¬ ∃ c : Fin 1 → ZMod 3, IsFoxColouring unknotDiagram 3 c ∧ ∃ i j, c i ≠ c j := by
  rintro ⟨c, -, i, j, hij⟩
  exact hij (by rw [Subsingleton.elim i j])
Axioms used: propext, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
trefoil_three_colouringsLean 4Proved here from basic factsFormally verified
/-- The trefoil diagram has exactly `9` Fox `3`-colourings: the `3` constant ones and `6` using
all three colours. Checked by trying all `27` colourings. -/
theorem trefoil_three_colourings :
    Fintype.card {c : Fin 3 → ZMod 3 // IsFoxColouring trefoilDiagram 3 c} = 9 := by
  decide
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
figure_eight_three_colouringsLean 4Proved here from basic factsFormally verified
/-- The figure-eight diagram has only the `3` constant Fox `3`-colourings, so it is **not
tricolourable**. Checked by trying all `81` colourings. -/
theorem figure_eight_three_colourings :
    Fintype.card {c : Fin 4 → ZMod 3 // IsFoxColouring figureEightDiagram 3 c} = 3 := by
  decide
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
trefoil_five_colouringsLean 4Proved here from basic factsFormally verified
/-- The trefoil diagram has only the `5` constant Fox `5`-colourings (all `125` checked). -/
theorem trefoil_five_colourings :
    Fintype.card {c : Fin 3 → ZMod 5 // IsFoxColouring trefoilDiagram 5 c} = 5 := by
  decide
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
figure_eight_five_colouringsLean 4Proved here from basic factsFormally verified
/-- The figure-eight diagram has `25` Fox `5`-colourings — `20` of them non-constant, such as
`A, B, C, D ↦ 0, 1, 4, 3` — so `5`-colourings tell it apart from the trefoil (all `625`
checked). -/
theorem figure_eight_five_colourings :
    Fintype.card {c : Fin 4 → ZMod 5 // IsFoxColouring figureEightDiagram 5 c} = 25 := by
  decide
Axioms used: propext, Classical.choice, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

The local algebra of Theorem 2, in any commutative ring, followed by Mathlib's dihedral quandle, whose self-distributivity is the general form of move III:

reidemeister_oneLean 4Proved here from basic factsFormally verified
/-- **Move I (a kink).** At a kink the over arc is also one of the under arcs, so the colouring
rule reads `2a = a + b`, which forces `b = a`: the kink adds no freedom and removes none. -/
theorem reidemeister_one {R : Type*} [CommRing R] (a b : R) : 2 * a = a + b ↔ b = a := by
  constructor
  · intro h
    linear_combination -h
  · intro h
    rw [h]
    ring
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
reidemeister_twoLean 4Proved here from basic factsFormally verified
/-- **Move II.** A strand of colour `x` passes over another strand twice; the lower strand is cut
into pieces `a`, `m`, `b`. The two crossings say `2x = a + m` and `2x = m + b`, which hold exactly
when the middle colour is `m = 2x - a` and the outgoing colour is `b = a`. So colourings before
and after the move correspond one to one. -/
theorem reidemeister_two {R : Type*} [CommRing R] (x a m b : R) :
    (2 * x = a + m ∧ 2 * x = m + b) ↔ (m = 2 * x - a ∧ b = a) := by
  constructor
  · rintro ⟨h1, h2⟩
    exact ⟨by linear_combination -h1, by linear_combination h1 - h2⟩
  · rintro ⟨rfl, rfl⟩
    constructor <;> ring
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
reidemeister_threeLean 4Proved here from basic factsFormally verified
/-- **Move III.** Strands with incoming colours `t` (top), `m` (middle) and `b` (bottom) cross;
the bottom strand passes under the other two in either order. Writing `x ◃ y = 2x - y` for the
colour of a strand `y` after it passes under `x`, the outgoing bottom colour is
`t ◃ (m ◃ b)` on one side of the move and `(t ◃ m) ◃ (t ◃ b)` on the other. They agree: this is
**self-distributivity**, the quandle axiom. -/
theorem reidemeister_three {R : Type*} [CommRing R] (t m b : R) :
    2 * t - (2 * m - b) = 2 * (2 * t - m) - (2 * t - b) := by
  ring
Axioms used: propext, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
dihedral_quandle_self_distribLean 4Applies a library theoremFormally verified
/-- Mathlib's **dihedral quandle** `Quandle.Dihedral n` is `ZMod n` with `a ◃ b = 2a - b`; Fox
colourings are exactly colourings by this quandle. Its self-distributivity is the general form of
`reidemeister_three`. This applies Mathlib's `Shelf.self_distrib` for the instance on
`Quandle.Dihedral n`. -/
theorem dihedral_quandle_self_distrib (n : ℕ) (x y z : Quandle.Dihedral n) :
    x ◃ (y ◃ z) = (x ◃ y) ◃ (x ◃ z) :=
  Shelf.self_distrib
Axioms used: propext, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

Linking numbers, the Hopf and Whitehead links, and the invariance under move II:

linkingNumberLean 4Formally verified
/-- The **linking number**: half the sum of the signs of the crossings between the components. -/
def linkingNumber (cs : List LinkCrossing) : ℤ := linkingSum cs / 2
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
hopf_linking_numberLean 4Proved here from basic factsFormally verified
/-- The (positive) **Hopf link** has two crossings between its components, both `+1`: linking
number `1`. So it cannot be pulled apart, since the unlink has linking number `0`. -/
theorem hopf_linking_number : linkingNumber [⟨true, 1⟩, ⟨true, 1⟩] = 1 := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
whitehead_linking_numberLean 4Proved here from basic factsFormally verified
/-- The **Whitehead link** (in its standard five-crossing diagram) has one self-crossing and
four crossings between its components, with signs `+1, -1, +1, -1`: linking number `0`, although
it is not the unlink. The linking number is not a complete invariant. -/
theorem whitehead_linking_number :
    linkingNumber [⟨false, 1⟩, ⟨true, 1⟩, ⟨true, -1⟩, ⟨true, 1⟩, ⟨true, -1⟩] = 0 := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
linking_sum_reidemeister_twoLean 4Proved here from basic factsFormally verified
/-- **Move II does not change the linking sum**: it creates or removes two crossings between the
same strands with opposite signs. (Move I creates a self-crossing, which is not counted; move III
only rearranges crossings without changing their signs.) -/
theorem linking_sum_reidemeister_two (cs : List LinkCrossing) (s : ℤ) :
    linkingSum (cs ++ [⟨true, s⟩, ⟨true, -s⟩]) = linkingSum cs := by
  simp [linkingSum, List.filter_append]
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

The Kauffman bracket from planar diagram (PD) codes: one quadruple of edge labels per crossing, listed anticlockwise from the incoming under-edge. The state sum is computed literally — every state, its circles counted by merging edge labels — and collected into a normal form of the Laurent polynomial (a sorted list of exponents with non-zero coefficients). The main definitions:

smoothingLean 4Formally verified
/-- Smoothing a crossing `(i, j, k, l)` joins its four edges in pairs: the **A-smoothing** joins
`i` with `j` and `k` with `l`; the **B-smoothing** joins `i` with `l` and `j` with `k`. -/
def smoothing (x : ℕ × ℕ × ℕ × ℕ) (s : Bool) : List (ℕ × ℕ) :=
  match x with
  | (i, j, k, l) => if s then [(i, j), (k, l)] else [(i, l), (j, k)]
Axioms used: No axiomsformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
bracketMonomialsLean 4Formally verified
/-- The **Kauffman bracket** state sum `⟨D⟩ = Σ_states A^(a - b) δ^(L - 1)`, as a list of
monomials (not yet collected). -/
def bracketMonomials (pd : PD) : List (ℤ × ℤ) :=
  (allStates pd.length).flatMap (stateMonomials pd)
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
crossingSignLean 4Formally verified
/-- The **sign** of a crossing `(i, j, k, l)` in a diagram with `2n` edges (`n ≥ 2`): the over
strand runs `l → j` (sign `+1`, right-handed) when `j` follows `l` along the knot, and `j → l`
(sign `-1`) when `l` follows `j`. -/
def crossingSign (n2 : ℕ) (x : ℕ × ℕ × ℕ × ℕ) : ℤ :=
  match x with
  | (_, j, _, l) =>
    if (j + n2 - l) % n2 = 1 then 1 else if (l + n2 - j) % n2 = 1 then -1 else 0
Axioms used: No axiomsformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
jonesMonomialsLean 4Formally verified
/-- The normalised bracket `f(D) = (-A³)^(-w(D)) ⟨D⟩`, in normal form. Substituting `A = t^(-1/4)`
turns it into the **Jones polynomial** `V(t)`: the monomial `A^e` becomes `t^(-e/4)`. -/
def jonesMonomials (pd : PD) : List (ℤ × ℤ) :=
  let w := writhe pd
  normalForm ((bracketMonomials pd).map (fun m => (m.1 - 3 * w, (-1) ^ w.natAbs * m.2)))
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
trefoilPDLean 4Formally verified
/-- A PD code of the **right-handed trefoil** (all three crossings positive). -/
def trefoilPD : PD := [(1, 5, 2, 4), (3, 1, 4, 6), (5, 3, 6, 2)]
Axioms used: No axiomsformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
mirrorTrefoilPDLean 4Formally verified
/-- A PD code of its **mirror image**, the left-handed trefoil: every crossing switched. -/
def mirrorTrefoilPD : PD := [(4, 1, 5, 2), (6, 3, 1, 4), (2, 5, 3, 6)]
Axioms used: No axiomsformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

and the computations of the example and of Corollary 6, each checked by evaluation:

bracket_trefoilLean 4Proved here from basic factsFormally verified
/-- `⟨right-handed trefoil⟩ = A⁻⁷ - A⁻³ - A⁵`, by evaluating the `8`-state sum. -/
theorem bracket_trefoil :
    normalForm (bracketMonomials trefoilPD) = [(-7, 1), (-3, -1), (5, -1)] := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
bracket_mirror_trefoilLean 4Proved here from basic factsFormally verified
/-- `⟨left-handed trefoil⟩ = -A⁻⁵ - A³ + A⁷`: the bracket of the mirror image is obtained by
replacing `A` with `A⁻¹`. -/
theorem bracket_mirror_trefoil :
    normalForm (bracketMonomials mirrorTrefoilPD) = [(-5, -1), (3, -1), (7, 1)] := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
writhe_trefoilsLean 4Proved here from basic factsFormally verified
/-- The writhes of the two trefoil diagrams are `+3` and `-3`. -/
theorem writhe_trefoils : writhe trefoilPD = 3 ∧ writhe mirrorTrefoilPD = -3 := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
jones_trefoilLean 4Proved here from basic factsFormally verified
/-- The Jones polynomial of the right-handed trefoil: `f = -A⁻¹⁶ + A⁻¹² + A⁻⁴`, i.e.
`V(t) = t + t³ - t⁴`. -/
theorem jones_trefoil : jonesMonomials trefoilPD = [(-16, -1), (-12, 1), (-4, 1)] := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
jones_mirror_trefoilLean 4Proved here from basic factsFormally verified
/-- The Jones polynomial of the left-handed trefoil: `f = A⁴ + A¹² - A¹⁶`, i.e.
`V(t) = t⁻¹ + t⁻³ - t⁻⁴`. -/
theorem jones_mirror_trefoil : jonesMonomials mirrorTrefoilPD = [(4, 1), (12, 1), (16, -1)] := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
jones_figure_eightLean 4Proved here from basic factsFormally verified
/-- The Jones polynomial of the figure-eight knot, `V(t) = t⁻² - t⁻¹ + 1 - t + t²`, is
symmetric under `t ↦ t⁻¹` — as it must be, since the figure-eight knot is its own mirror image. -/
theorem jones_figure_eight :
    jonesMonomials figureEightPD = [(-8, 1), (-4, -1), (0, 1), (4, -1), (8, 1)] := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor
trefoil_jones_ne_mirrorLean 4Proved here from basic factsFormally verified
/-- The two trefoils have **different Jones polynomials**. Together with the theorem that the
Jones polynomial is a knot invariant (proved in the lesson, not here), this shows the trefoil is
not equivalent to its mirror image. -/
theorem trefoil_jones_ne_mirror :
    jonesMonomials trefoilPD ≠ jonesMonomials mirrorTrefoilPD := by
  decide
Axioms used: propextformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

Finally the kink identity of Theorem 5(b), in any commutative ring with AB=1AB = 1:

kink_identityLean 4Proved here from basic factsFormally verified
/-- **The kink identity.** With `B = A⁻¹` and `δ = -A² - B²`, removing a positive kink multiplies
the bracket by `Aδ + B = -A³` (and a negative kink by `A + Bδ = -B³`). This is why the bracket
is not invariant under move I, and why the factor `(-A³)^(-writhe)` repairs it. -/
theorem kink_identity {R : Type*} [CommRing R] (A B : R) (h : A * B = 1) :
    A * (-A ^ 2 - B ^ 2) + B = -A ^ 3 ∧ A + B * (-A ^ 2 - B ^ 2) = -B ^ 3 := by
  constructor
  · linear_combination (-B) * h
  · linear_combination (-A) * h
Axioms used: propext, Quot.soundformal/Lumenary/KnotTheory.leanTry it in the Lean web editor

What is and is not formalised. Formalised: the definitions of colourings, linking numbers, the bracket state sum, writhe and Jones polynomial on diagram codes; the colouring counts; the local algebra of moves I–III for colourings and of move II for linking numbers; the kink identity; and the bracket and Jones polynomials of both trefoils and the figure-eight knot. Not formalised: knots as embeddings, ambient isotopy, Reidemeister's theorem, the invariance of the bracket under moves II and III on arbitrary PD codes, Seifert surfaces and genus.

ComputationC

Colourings, determinants and Jones polynomials by computer

The first program reads PD codes of six knots, builds the colouring equations, counts pp-colourings by linear algebra mod pp (confirmed by brute force on small cases), and computes each knot's determinant exactly.

Fox colourings and knot determinantsPythonExact computationExhaustive finite checkComputationally tested
"""Fox colourings and the determinant of a knot.

From a planar diagram (PD) code we find the arcs of the diagram (edges joined
where they pass over a crossing) and the colouring equations: at a crossing
whose over-arc is x and whose under-arcs are y and z, 2x = y + z mod p. The
number of Fox p-colourings is p to the power of the dimension of the solution
space, found by Gaussian elimination mod p. The determinant of the knot is
the absolute value of any (n-1) x (n-1) minor of the colouring matrix,
computed with exact fractions. A knot has a non-constant p-colouring (p an
odd prime) exactly when p divides its determinant. Brute force over all
colourings checks the linear algebra on the smallest cases. Evidence: exact
computation for these diagrams.
"""

from fractions import Fraction
from itertools import product

KNOTS = {
    "unknot (1 kink)": [(1, 2, 2, 1)],
    "3_1": [(1, 5, 2, 4), (3, 1, 4, 6), (5, 3, 6, 2)],
    "4_1": [(4, 2, 5, 1), (8, 6, 1, 5), (6, 3, 7, 4), (2, 7, 3, 8)],
    "5_1": [(1, 6, 2, 7), (3, 8, 4, 9), (5, 10, 6, 1), (7, 2, 8, 3),
            (9, 4, 10, 5)],
    "5_2": [(1, 4, 2, 5), (3, 8, 4, 9), (5, 10, 6, 1), (9, 6, 10, 7),
            (7, 2, 8, 3)],
    "6_1": [(1, 4, 2, 5), (7, 10, 8, 11), (3, 9, 4, 8), (9, 3, 10, 2),
            (5, 12, 6, 1), (11, 6, 12, 7)],
}

def arcs(pd):
    """Map each edge label to its arc number (edges j, l continue over)."""
    parent = {}

    def find(x):
        while parent.setdefault(x, x) != x:
            x = parent[x]
        return x

    for (i, j, k, l) in pd:
        for e in (i, k):
            find(e)
        parent[find(j)] = find(l)
    roots = sorted({find(e) for c in pd for e in c})
    return {e: roots.index(find(e)) for c in pd for e in c}

def colouring_matrix(pd):
    """Rows 2x - y - z, one per crossing, columns indexed by arcs."""
    arc = arcs(pd)
    n = len(set(arc.values()))
    rows = []
    for (i, j, k, l) in pd:
        row = [0] * n
        row[arc[j]] += 2
        row[arc[i]] -= 1
        row[arc[k]] -= 1
        rows.append(row)
    return rows

def rank_mod_p(rows, p):
    """Rank of an integer matrix over the field Z/p (p prime)."""
    m = [[x % p for x in row] for row in rows]
    rank, cols = 0, len(m[0]) if m else 0
    for c in range(cols):
        pivot = next((r for r in range(rank, len(m)) if m[r][c]), None)
        if pivot is None:
            continue
        m[rank], m[pivot] = m[pivot], m[rank]
        inv = pow(m[rank][c], p - 2, p)
        m[rank] = [x * inv % p for x in m[rank]]
        for r in range(len(m)):
            if r != rank and m[r][c]:
                f = m[r][c]
                m[r] = [(x - f * y) % p for x, y in zip(m[r], m[rank])]
        rank += 1
    return rank

def count_colourings(pd, p):
    """Number of Fox p-colourings = p^(arcs - rank mod p)."""
    rows = colouring_matrix(pd)
    return p ** (len(rows[0]) - rank_mod_p(rows, p))

def brute_force_count(pd, p):
    """Count Fox p-colourings by trying every assignment (small cases)."""
    rows = colouring_matrix(pd)
    n = len(rows[0])
    return sum(all(sum(a * c for a, c in zip(row, col)) % p == 0
                   for row in rows)
               for col in product(range(p), repeat=n))

def determinant(rows):
    """Exact determinant of a square matrix by Gaussian elimination."""
    m = [[Fraction(x) for x in row] for row in rows]
    det = Fraction(1)
    for c in range(len(m)):
        pivot = next((r for r in range(c, len(m)) if m[r][c] != 0), None)
        if pivot is None:
            return Fraction(0)
        if pivot != c:
            m[c], m[pivot] = m[pivot], m[c]
            det = -det
        det *= m[c][c]
        for r in range(c + 1, len(m)):
            f = m[r][c] / m[c][c]
            m[r] = [x - f * y for x, y in zip(m[r], m[c])]
    return det

def knot_determinant(pd):
    """|det| of the colouring matrix with its last row and column deleted."""
    rows = colouring_matrix(pd)
    if len(rows) == 1:
        return 1
    minor = [row[:-1] for row in rows[:-1]]
    return abs(int(determinant(minor)))

def main():
    print("Fox colourings: 2 * over = under + under (mod p) at each crossing")
    print("  knot            arcs  det  3-col  5-col  7-col  tricolourable")
    for name, pd in KNOTS.items():
        n = len(colouring_matrix(pd)[0])
        det = knot_determinant(pd)
        counts = [count_colourings(pd, p) for p in (3, 5, 7)]
        tri = "yes" if counts[0] > 3 else "no"
        print(f"  {name:<15} {n:4d} {det:4d} {counts[0]:6d} {counts[1]:6d}"
              f" {counts[2]:6d}  {tri}")
    checks = [(name, p) for name in ("3_1", "4_1", "5_1") for p in (3, 5)]
    agree = all(count_colourings(KNOTS[k], p) == brute_force_count(KNOTS[k], p)
                for k, p in checks)
    print(f"  brute force agrees on {len(checks)} small cases: {agree}")
    print()
    print("Constant colourings always work, giving p of them. A non-constant")
    print("p-colouring exists exactly when p divides the determinant. 3_1 is")
    print("tricolourable and the unknot is not, so 3_1 is knotted. 4_1 and 5_1")
    print("share det = 5 and the colouring counts above, yet they are different")
    print("knots: their Jones polynomials differ. Invariants can fail to")
    print("distinguish; they never wrongly separate.")
    print()
    print("Epistemic status: exact computation for these PD codes, with brute")
    print("force confirming the linear algebra on small cases. That colouring")
    print("counts are knot invariants is proved in the lesson (Reidemeister).")

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

Notice the pair 414_1 and 515_1: same determinant, same colouring counts, different knots. An invariant that agrees on two knots tells you nothing.

The second program evaluates the bracket state sum and the Jones polynomial for the same knots. It checks that a kink changes the bracket by −A±3-A^{\pm 3} but leaves VV alone, and that V(1)=1V(1) = 1 for knots. It also compares each V(t)V(t) with V(t−1)V(t^{-1}).

Kauffman bracket and Jones polynomial from PD codesPythonExact computationComputationally tested
"""The Kauffman bracket and the Jones polynomial, computed from PD codes.

A knot diagram is given by a planar diagram (PD) code: one quadruple
(i, j, k, l) per crossing, listing the four edge labels anticlockwise and
starting from the incoming under-edge. The Kauffman bracket is the state sum
over all 2^n ways of smoothing the crossings,

    <D> = sum over states of A^(#A - #B) * d^(loops - 1),  d = -A^2 - A^(-2),

and the Jones polynomial is V(t) = (-A^3)^(-writhe) <D> with A = t^(-1/4).
We compute both exactly (Laurent polynomials as dictionaries exponent ->
coefficient), check that adding a kink changes the bracket by -A^(+-3) but
not V, check that V(1) = 1, and compare each knot with its mirror image.
Evidence: exact computation on these diagrams; the invariance theorems are
proved in the lesson.
"""

from collections import defaultdict
from itertools import product

KNOTS = {
    "3_1 (right trefoil)": [(1, 5, 2, 4), (3, 1, 4, 6), (5, 3, 6, 2)],
    "3_1 mirror (left)": [(4, 1, 5, 2), (6, 3, 1, 4), (2, 5, 3, 6)],
    "4_1 (figure eight)": [(4, 2, 5, 1), (8, 6, 1, 5), (6, 3, 7, 4),
                           (2, 7, 3, 8)],
    "5_1": [(1, 6, 2, 7), (3, 8, 4, 9), (5, 10, 6, 1), (7, 2, 8, 3),
            (9, 4, 10, 5)],
    "5_2": [(1, 4, 2, 5), (3, 8, 4, 9), (5, 10, 6, 1), (9, 6, 10, 7),
            (7, 2, 8, 3)],
    "6_1": [(1, 4, 2, 5), (7, 10, 8, 11), (3, 9, 4, 8), (9, 3, 10, 2),
            (5, 12, 6, 1), (11, 6, 12, 7)],
}

def loops(pd, state):
    """Number of circles after smoothing: A joins (i,j),(k,l); B (i,l),(j,k)."""
    parent = {}

    def find(x):
        while parent.setdefault(x, x) != x:
            x = parent[x]
        return x

    for (i, j, k, l), s in zip(pd, state):
        pairs = [(i, j), (k, l)] if s == "A" else [(i, l), (j, k)]
        for a, b in pairs:
            parent[find(a)] = find(b)
    return len({find(x) for crossing in pd for x in crossing})

def multiply(p, q):
    """Product of Laurent polynomials stored as {exponent: coefficient}."""
    out = defaultdict(int)
    for e1, c1 in p.items():
        for e2, c2 in q.items():
            out[e1 + e2] += c1 * c2
    return {e: c for e, c in out.items() if c}

def bracket(pd):
    """The Kauffman bracket <D> as {exponent of A: coefficient}."""
    if not pd:
        return {0: 1}
    delta = {2: -1, -2: -1}
    total = defaultdict(int)
    for state in product("AB", repeat=len(pd)):
        term = {state.count("A") - state.count("B"): 1}
        for _ in range(loops(pd, state) - 1):
            term = multiply(term, delta)
        for e, c in term.items():
            total[e] += c
    return {e: c for e, c in sorted(total.items()) if c}

def crossing_sign(crossing, edges):
    """+1 if the over strand runs l -> j (right-handed), -1 if j -> l."""
    _, j, _, l = crossing
    if (j - l) % edges == 1:
        return 1
    if (l - j) % edges == 1:
        return -1
    raise ValueError("cannot orient the over strand (use n >= 2)")

def writhe(pd):
    """Sum of the crossing signs."""
    return sum(crossing_sign(x, 2 * len(pd)) for x in pd)

def jones(pd):
    """V(t) as {exponent of t: coefficient}, using A = t^(-1/4)."""
    w = writhe(pd)
    sign = -1 if w % 2 else 1
    f = {e - 3 * w: sign * c for e, c in bracket(pd).items()}
    assert all(e % 4 == 0 for e in f), "a knot's f has exponents in 4Z"
    return {-e // 4: c for e, c in sorted(f.items(), reverse=True)}

def mirror_jones(v):
    """V of the mirror image: t -> 1/t."""
    return {-e: c for e, c in sorted(v.items(), key=lambda kv: -kv[0])}

def add_kink(pd, positive=True):
    """Add a kink on the last edge 2n; returns a PD code with n + 1 crossings."""
    n2 = 2 * len(pd)
    new, g = [], n2 + 2
    for (i, j, k, l) in pd:
        # the occurrence of 2n where that edge *ends* gets the new label 2n + 2
        if i == n2:
            i = g
        elif j == n2 and l == 1:
            j = g
        elif l == n2 and j == 1:
            l = g
        new.append((i, j, k, l))
    kink = (n2, g, n2 + 1, n2 + 1) if positive else (n2, n2 + 1, n2 + 1, g)
    return new + [kink]

def show(poly, var="t"):
    """Format {exponent: coefficient} as text, highest power first."""
    terms = []
    for e, c in sorted(poly.items(), key=lambda kv: -kv[0]):
        mag = "" if abs(c) == 1 and e != 0 else str(abs(c))
        power = "" if e == 0 else (var if e == 1 else f"{var}^{e}")
        sign = "-" if c < 0 else "+"
        terms.append(f"{sign} {mag}{power}".strip())
    text = " ".join(terms)
    return text[2:] if text.startswith("+ ") else "-" + text[2:]

def main():
    trefoil = KNOTS["3_1 (right trefoil)"]
    print("Kauffman bracket of the right trefoil (8 states):")
    print("  <3_1> =", show(bracket(trefoil), "A"), " writhe", writhe(trefoil))
    for positive in (True, False):
        kinked = add_kink(trefoil, positive)
        print(f"  with a {'positive' if positive else 'negative'} kink:",
              show(bracket(kinked), "A"), " writhe", writhe(kinked))
    same = jones(add_kink(trefoil)) == jones(add_kink(trefoil, False)) \
        == jones(trefoil)
    print("  V unchanged by either kink:", same)
    print()
    print("Jones polynomials V(t):")
    for name, pd in KNOTS.items():
        v = jones(pd)
        amph = "yes" if v == mirror_jones(v) else "no"
        print(f"  {name:<20} {show(v)}")
        print(f"  {'':<20} V(1) = {sum(v.values())}, V(t) = V(1/t)? {amph}")
    print()
    print("As V is an invariant, V(1/t) != V(t) proves that 3_1, 5_1, 5_2 and")
    print("6_1 are not equivalent to their mirror images. For 4_1, V(t) = V(1/t)")
    print("is consistent with mirror symmetry but does not prove it.")
    print()
    print("Epistemic status: exact computation for these PD codes. That V is a")
    print("knot invariant (so equal knots have equal V) is a theorem proved in")
    print("the lesson; the program only evaluates it.")

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

Both programs are exact computations on particular diagrams. The state sum has 2n2^n terms, so this method is hopeless for large knots. Computing the Jones polynomial is #P-hard in general (Jaeger, Vertigan and Welsh, 1990).

Explore

Explore: colour the knots

Click the arcs to colour them, aiming for the rule "all three colours equal or all different at every crossing". Then press Try every colouring. The trefoil has 99 valid colourings, 66 of them non-constant; the unknot (drawn with one twist) and the figure-eight knot have only the 33 constant ones. The Hopf link shows its linking number. Ask yourself, each time, what the result does and does not prove.

Tricolouring knots and links

Colour every arc of the diagram. At each crossing, the three arcs that meet must be all the same colour or all different.

???

Click an arc to change its colour (or focus it and press Enter, or 1, 2, 3). An arc runs from one under-crossing to the next.

colour 1 (terracotta, circle)colour 2 (violet, triangle)colour 3 (teal, square)
Trefoil3₁
Crossings in this diagram
3
Crossing number (fewest possible)
3

Arcs coloured: 0 of 3.

Why this rule? Any two diagrams of the same knot are related by three kinds of local moves, the Reidemeister moves: adding or removing a twist, sliding one strand over another, and sliding a strand past a crossing. Each move turns a valid colouring with two or more colours into another one.

The trefoil can be tricoloured and the unknot cannot. Because tricolourability is an invariant, no amount of wiggling turns the trefoil into the unknot: the trefoil really is knotted.

So tricolourability is a knot invariant: if one diagram of a knot can be tricoloured, every diagram of it can. A plain circle has just one arc, so the unknot cannot be tricoloured.

Exercises

Exercises

1. Knot theory

Warm-upHuman

Which of these are knot invariants (the same for all diagrams of equivalent knots)? (Choose all that apply.)

Choose all that apply

2. Knot theory

Warm-upHuman

How many Fox 3-colourings (including the constant ones) does the standard 3-crossing diagram of the trefoil have?

3. Knot theory

CoreHuman

Neither the unknot nor the figure-eight knot is tricolourable. What can you conclude from this alone?

Choose one

4. Knot theory

CoreHuman

Solomon's knot, found in Roman mosaics, medieval manuscripts and textiles from many cultures, is a link of two loops whose standard diagram has 44 crossings, all between the two components and all of the same sign +1+1. What is its linking number?

5. Knot theory

CoreHuman

In the proof that Fox colourings survive move II, a strand of colour xx passes over a strand cut into arcs a,m,ba, m, b, with equations 2x=a+m2x = a + m and 2x=m+b2x = m + b. Why does this show that colourings before and after the move correspond one to one?

Choose one

6. Knot theory

CoreHuman

The standard diagram of the cinquefoil 515_1 (the (2,5)(2, 5) torus knot) has 55 crossings, and Seifert's algorithm produces 22 Seifert circles. What is the genus of the resulting Seifert surface?

7. Knot theory

CoreHuman

The right-handed trefoil has Jones polynomial V(t)=t+t3−t4V(t) = t + t^3 - t^4. What is the Jones polynomial of the left-handed trefoil, its mirror image?

Choose one

8. Knot theory

CoreFormal

Which of these statements is actually proved in the lesson's Lean file?

Choose one

9. Knot theory

CoreComputational

Write count_colourings(n_arcs, crossings, p) that counts the Fox pp-colourings of a diagram by brute force. crossings is a list of triples (over, under1, under2) of arc numbers in range(n_arcs); a colouring is a tuple of colours in range(p), and it is valid if (2 * c[over] - c[under1] - c[under2]) % p == 0 at every crossing.

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

10. Knot theory

StretchHuman

The figure-eight knot has V(t)=t−2−t−1+1−t+t2V(t) = t^{-2} - t^{-1} + 1 - t + t^2, which satisfies V(t)=V(t−1)V(t) = V(t^{-1}). What does this prove?

Choose one
Common misconceptionsH

Common misconceptions

Misconception

"If an invariant agrees on two knots, they are the same knot." The unknot and the figure-eight knot are both not tricolourable, yet the figure-eight knot is knotted (its 55-colourings show it). 414_1 and 515_1 have the same determinant; 515_1 and the ten-crossing knot 1013210_{132} have the same Jones polynomial. Invariants can only prove that knots are different.

Misconception

"The crossing number can be read off a diagram." A diagram only gives an upper bound: the unknot has diagrams with as many crossings as you like. Proving a lower bound needs an invariant. For reduced alternating diagrams the number of crossings is the crossing number — one of Tait's conjectures, proved with the Jones polynomial by Kauffman, Murasugi and Thistlethwaite (1987).

Misconception

"The left- and right-handed trefoils are the same: just turn one over." Turning a knot over is a rotation in space, which is an isotopy and cannot change handedness. Mirroring is a reflection, which is not. Corollary 6 shows the two trefoils are genuinely different.

Misconception

"Linking number zero means the link comes apart." The Whitehead link and the Borromean rings have all linking numbers 00 but cannot be separated. The linking number only counts how often one component winds around the other, with signs.

Misconception

"Reidemeister's theorem gives an easy algorithm for untying knots." It says a sequence of moves exists, not how long it is or how to find it. Sometimes a diagram of the unknot must first get more complicated before it can be simplified. Lackenby's bound (236c)11(236c)^{11} is polynomial but huge, and general knot equivalence algorithms rely on deep 3-manifold theory.

ViewpointsH

Many ways of seeing

Topology— The knot complement and the knot group

A topologist studies a knot through its complement S3∖KS^3 \setminus K. By Gordon and Luecke (1989), the complement determines the knot up to mirror image and orientation. Its fundamental group, the knot group, has a presentation read from any diagram (Wirtinger): one generator for each arc, a loop going once under that arc, and one relation per crossing. For the trefoil it is ⟨x,y∣x2=y3⟩\langle x, y \mid x^2 = y^3 \rangle, which is non-abelian; for the unknot it is Z\Z. Fox colourings are exactly the homomorphisms from the knot group to the dihedral group DpD_p that send each Wirtinger generator to a reflection. That is why they are invariants, seen without Reidemeister moves. The Seifert surface leads to the Alexander polynomial (via a Seifert matrix) and to the four-dimensional questions of slice knots and concordance in low-dimensional topology.

Algebra— Quandles: the algebra of crossings

The three conditions behind Theorem 2 — x▹x=xx \triangleright x = x, y↦x▹yy \mapsto x \triangleright y bijective, and self-distributivity — are the axioms of a quandle (David Joyce, 1982; Sergei Matveev, 1982, who called them distributive groupoids). Every knot has a fundamental quandle, generated by its arcs with one relation per crossing. Joyce and Matveev proved that it is almost a complete invariant: it determines an oriented knot up to taking the mirror image and reversing the orientation at the same time. Colourings by a quandle QQ are homomorphisms from the fundamental quandle to QQ; Fox colourings use the dihedral quandle Z/p\Z/p, and Mathlib's Quandle.Dihedral is exactly that structure. The price of completeness is that quandles are hard to compare, so in practice one counts colourings by small quandles — invariants again.

Geometry— Hyperbolic knots

William Thurston showed that every knot is a torus knot (lying on an unknotted torus, like 313_1 and 515_1), a satellite knot (tied inside a knotted solid torus), or hyperbolic: its complement carries a complete metric of constant curvature −1-1 with finite volume. The figure-eight knot is hyperbolic, and its complement is built from two regular ideal tetrahedra; its volume is 2.0298832…2.0298832\dots By Mostow–Prasad rigidity this metric is unique, so geometric quantities such as the hyperbolic volume are knot invariants. Most knots in the tables are hyperbolic, and programs such as SnapPea and SnapPy compute their geometry to identify them. See low-dimensional topology.

Physics— From vortex atoms to quantum field theory

Knot tables began with physics. In 1867 William Thomson (Lord Kelvin) proposed that atoms are knotted vortices in the ether, and Peter Guthrie Tait set out to tabulate knots as a periodic table. The theory of atoms failed; the tables survived. A century later the Kauffman bracket appeared as a state sum like a partition function in statistical mechanics, and Edward Witten (1989) explained the Jones polynomial as an expectation value of a "Wilson loop" in Chern–Simons quantum field theory. Witten's path integral is a heuristic, not a rigorous definition. Nicolai Reshetikhin and Vladimir Turaev (1991) gave a rigorous construction of the resulting invariants of knots and 3-manifolds using quantum groups. See mathematical foundations of quantum mechanics.

Category theory— Tangles and categorification

Cutting a knot diagram by horizontal lines exhibits it as a composite of elementary pieces: caps, cups and crossings. Tangles — pieces of knots with ends on two horizontal lines — form a braided monoidal category. Its morphisms compose by stacking, and the Reidemeister moves are among its relations. The Jones polynomial comes from a functor from this category to representations of the quantum group Uq(sl2)U_q(\mathfrak{sl}_2) (Reshetikhin–Turaev). Mikhail Khovanov (2000) categorified the Jones polynomial. He replaced it by a chain complex of graded vector spaces built from the states of the bracket, whose homology is a knot invariant and whose graded Euler characteristic is VKV_K. Khovanov homology is strictly stronger: it detects the unknot (Kronheimer and Mrowka, 2011), which the Jones polynomial is not known to do. See monoidal categories.

Computation— How hard is it to recognise the unknot?

Recognising the unknot is decidable (Haken, 1961) and lies in NP (Hass, Lagarias and Pippenger, 1999): a short certificate is a normal disc bounded by the knot. It also lies in co-NP (Lackenby), but no polynomial-time algorithm is known. Invariants have their own complexity. Fox colouring counts and the determinant are computed in polynomial time by linear algebra, as in the first experiment. The Jones polynomial is #P-hard to compute exactly in general (Jaeger, Vertigan and Welsh, 1990). Yet approximating it at certain roots of unity is something a quantum computer does efficiently (Aharonov, Jones and Landau, 2006). Knots sit at a meeting point of topology and complexity theory.

History & global context

History and global context

  • Knots as craft and record. Knotted cords recorded numbers in the Andean khipu and in other cultures; decorative knotting has long traditions in China, Korea and Japan, in Celtic and Islamic art, and among sailors everywhere.
  • First mathematics. Alexandre-Théophile Vandermonde (1771) listed knot problems among questions of "geometry of position". Carl Friedrich Gauss (1833) wrote down the linking integral. His student Johann Benedict Listing coined the word topology in 1847 and studied knots.
  • Tables. Kelvin's vortex atoms (1867) inspired Peter Guthrie Tait, Thomas Kirkman and Charles Little to tabulate knots up to ten crossings (1876–1899), together with conjectures about alternating knots.
  • Invariants. Max Dehn (1914) proved that the two trefoils differ. James Waddell Alexander (1928) introduced the Alexander polynomial, and Kurt Reidemeister (1927), and independently Alexander and Garland Briggs (1926), the moves. Herbert Seifert (1934) constructed his surfaces. Ralph Fox (1950s–60s) popularised colourings.
  • Algorithms and geometry. Wolfgang Haken (1961) found an algorithm for recognising the unknot. William Thurston's hyperbolic geometry (late 1970s) transformed the subject.
  • The Jones revolution. Vaughan Jones, a New Zealand mathematician working on operator algebras, discovered his polynomial in 1984. Louis Kauffman found the bracket state sum (1987). Kauffman, Kunio Murasugi and Morwen Thistlethwaite used it to prove Tait's century-old conjectures on alternating knots (1987). Edward Witten connected it to quantum field theory (1989); Jones and Witten received Fields Medals in 1990. Mikhail Khovanov categorified it (2000).
Further reading

Further reading

  • Colin C. Adams, The Knot Book (1994) — an inviting first book, with many open problems and exercises.
  • W. B. Raymond Lickorish, An Introduction to Knot Theory (1997) — rigorous; Reidemeister moves, the Jones polynomial and Seifert surfaces.
  • Dale Rolfsen, Knots and Links (1976) — the classic, with the standard knot table.
  • Peter R. Cromwell, Knots and Links (2004).
  • Charles Livingston, Knot Theory (1993).