Hilbert's Tenth Problem, Part V: The MRDP Theorem
Author: silverxz
Proofreader: Acidmoon
This article proves that Diophantine sets are equivalent to recursively enumerable sets.
We have already noted that the direction from Diophantine sets to recursively enumerable sets is fairly straightforward. Let there be a Diophantine set S and its corresponding Diophantine equation D(x1,...,xn,y1,...,ym)=0; for (a1,...,an)∈Nn, we need only have a Turing machine M systematically try every possible y1,...,ym to see whether D(a1,...,an,y1,...,ym)=0 holds. If (a1,...,an)∈S, the machine will eventually halt. The candidates must, of course, be enumerated in a reasonable way that guarantees every possible solution will be reached in finite time.
There is a subtle point here: given S, we do not know what D is. Yet such a D always exists, so the corresponding Turing machine M also exists.
That completes this direction of the proof. What really concerns us is how to prove that every recursively enumerable set is Diophantine. Our method is to construct Diophantine functions and relations that simulate each computational step of a Turing machine. This approach is not unusual. Readers familiar with basic computability theory may know the computation history method, a general technique used in undecidability proofs; the idea used here is much the same.
Diophantine Relations
We have already mentioned that a Diophantine relation is essentially the same thing as a Diophantine set, and that a Diophantine function can be viewed as a special Diophantine set or relation. Readers may not yet have an intuitive sense of what kinds of constructions this permits, however, so I will begin with a few simple examples before turning to the proof.
Perhaps the simplest example is the unary relation (predicate) “is even,” characterized as follows:
Even(a):=∃y(a=2y)
Why is this a Diophantine relation? Let D(x,y)=x−2y. The equation D(x,y)=0, with x as its parameter and y as its unknown, defines the Diophantine set S as follows:
S={a∈N∣∃y(D(a,y)=0)}
This shows that Even is a Diophantine relation. Note that because we have restricted the solutions of Diophantine equations to natural numbers, all existential quantifiers ∃ are understood to range over the natural numbers.
Similarly, ≥,>,=,<,≤,∣ (divisibility) are also Diophantine binary relations. Taking ≥ as an example, we may write
≥(a,b):=∃x(a=b+x)
Of course, ≥(a,b) is rather awkward notation; from here on, we will write such binary relations in the customary form a≥b instead.
Next come Diophantine functions. Recall that a multivariable function on the natural numbers f(x1,...,xn) is itself, in essence, a subset of the relevant Cartesian product F={(a1,...,an,f(a1,...,an))∣(a1,...,an)∈Nn}⊂Nn+1, so when we say that f is a Diophantine function, what we really mean is that F is a Diophantine set or relation. Addition, subtraction, and multiplication are naturally Diophantine functions. Another example is the remainder function rem(b,c), defined as the remainder when b is divided by c. Since
a=rem(b,c)⇔a<c & c∣(b−a)
—that is, a is the remainder when b is divided by c—is equivalent to a<c and c divides b−a; therefore, this is a Diophantine function. Wait, did you say “&”? That is logical conjunction. Recall that we proved Diophantine sets are closed under intersection and union. In the language of Diophantine relations, this means that Diophantine relations are closed under logical AND and OR. We may therefore join simple Diophantine relations and functions with logical connectives to construct highly complex relations. Consequently, =, which was not listed above, is also Diophantine, because it is > or <. Likewise, integer division is a Diophantine function. Since all our arithmetic takes place in the natural numbers, all division below means integer division by default.
Two further elementary facts are useful. First, nesting Diophantine relations or adding more existential quantifiers outside them still yields a Diophantine relation, because we can always expand the definitions and move every existential quantifier to the outermost level. We should make full use of this freedom to introduce existential quantifiers in Diophantine relations; many later constructions rely on it: rather than constructing the desired object directly, we describe its properties and use existential quantifiers to “select” it. Second, for a Diophantine set S, S×Nk is also Diophantine; this merely adds a few irrelevant variables to the corresponding equation. We therefore need not worry about matching the number of variables when applying logical connectives—we can simply “pad” the sets as needed.
Combining these facts with Bézout’s identity from number theory, readers can verify that the greatest-common-divisor function gcd is also Diophantine.
a=gcd(b,c)⇔bc>0 & a∣b & a∣c & ∃xy(a=bx−cy)
By now, readers should have more confidence in our proof: Diophantine relations are indeed quite expressive. Our goal is to express the following statement with such relations. Given a recursively enumerable set S⊂Nn, there exist a Turing machine M, an input (a1,...,an), and a number of steps k, such that (a1,...,an)∈S is equivalent to M halting after k steps (that is, reaching the final state qf). We therefore need a Diophantine function capable of simulating k steps of a Turing machine’s execution.
To simulate k steps of execution, we must of course first simulate a single step. To do that, we must at least determine how to encode the Turing machine’s various states and its operation. Crucially, this encoding must itself be “Diophantine.”
Encoding a Turing Machine
Let us review the “information” contained in a Turing machine: a finite set of states Q={q1,...,q∣Q∣}, in which q1 is the initial state, q∣Q∣ is the final state (also denoted qf); and a finite alphabet Σ={0,1,...,∣Σ∣−1}, in which 0 is the blank symbol. We will use ∣Q∣ and ∣Σ∣ for the sizes of the state set and the alphabet, thereby saving a few letters. Finally, there is a transition function.
A Turing machine’s transition function is usually defined as a single whole. For convenience, we divide it into three parts here. Suppose the machine is in state qi, and the symbol at the current position is sj. Let the index of the state reached by the transition be Q(i,j)∈{1,...,∣Q∣}, the index of the symbol written by the machine be Σ(i,j)∈{0,1,...,∣Σ∣−1}, and the direction in which the tape head moves be D(i,j)∈{−,L,R} (stay, move left, or move right, which we may represent as {0,1,2}). We thus obtain three functions Q(i,j),Σ(i,j),D(i,j), where Q and Σ are once again “overloaded” to save letters. Their meanings should be clear from context.
For the Turing machine, these functions are meaningful only when 1≤i≤∣Q∣,0≤j≤∣Σ∣−1 holds. But to make them Diophantine functions, we must extend their domains to N×N. The values assigned on the extended portion actually depend on what we will need later; here we simply specify them. In these otherwise meaningless cases, let Q(i,j) equal i, Σ(i,j) equal j, and D(i,j) equal −. This means invalid arguments leave the state, symbol, and direction unchanged. We now claim that the functions Q,Σ,D are all Diophantine.
This is because each amounts to modifying a Diophantine function (f(i,j)=j and so on) at finitely many points (1≤i≤∣Q∣,1≤j≤∣Σ∣), so we can simply use a logical expression to enumerate the cases. For the simplest example, suppose I want to describe a function whose value at 1 is 2, and which equals g(x) everywhere else. Call it f(x): I need only write
y=f(x)⇔(x=1 & y=2)∨(x=1 & y=g(x))
Here, provided that g(x) is a Diophantine function, f(x) is one as well. The same applies to Q,Σ,D: we need only enumerate the finitely many valid positions, then assign the “remaining cases” another Diophantine function of our choosing. This characterizes the Turing machine itself; Q,Σ,D will also be the notation used below.
We must also describe the state of the Turing machine during execution: the string on the tape (s1,...,sl), the current state qi, and the tape head’s position. These three quantities are often called the machine’s configuration—its instantaneous state during execution. We need a suitable way to record them. Using s1,...,sl directly will not work, because l may grow linearly as the machine runs, whereas a Diophantine equation always has only finitely many unknowns. We therefore need the technique of tuple encoding.
Encoding Tuples: Cantor Encoding and Positional Encoding
(We actually use only positional encoding. Cantor encoding is also simple and elegant, however, so I will present it as well. Comparing the two should make it clearer why we choose positional encoding.)
We begin with a relatively “classical” method: Cantor encoding. First, how can we encode (a,b)∈N2 as a single natural number? Cantor supplied a beautiful method. Readers can verify that the following function Cantor gives a bijection N2→N.
Cantor(a,b)↦2(a+b)2+3a+b
Readers who are not interested may simply accept this result. If you have trouble verifying it, try drawing a two-dimensional table and substituting (0,0),(0,1),(1,0),...; you may notice something interesting.
This is a useful encoding: it is a Diophantine function, and given a Cantor code c, the functions that recover a,b, namely ElemA(c),ElemB(c), are Diophantine as well. For ElemA(c), for example, we have
a=ElemA(c)⇔∃b(Cantor(a,b)=c)
Furthermore, a triple may be represented by Cantor3(a,b,c)=Cantor(a,Cantor(b,c)); the coordinate functions Elem are similar. Continuing inductively, we obtain Cantor encodings for tuples of any fixed length Cantorn. Note, however, that here n must be a fixed constant; it cannot be supplied as a variable input.
This encoding makes it easy both to encode a fixed-length tuple as a natural number and to recover it. Should we therefore use it for our tuples? No. Useful though it is, it is not quite enough: variable-length tuples are difficult to handle, and more complex operations such as concatenation are harder still.
We therefore introduce another encoding, called positional encoding; it applies when the tuple’s entries have an upper bound.
Let there be a tuple (x1,...,xn), whose entries have an upper bound b>xi; we may then use base b. Define
ax=x1+x2b+...+xnbn−1
Then (ax,b,n) is called a positional encoding of (x1,...,xn); b is called the encoding’s base or radix. It records the tuple length n, the radix b, and its value in base b, namely ax. Readers need not understand the principle behind Cantor encoding, but they do need to understand positional encoding—which is simply place-value notation—because we will make concrete use of many properties of this expression, really just properties of numeral systems. They reveal what an elegant choice this is.
Sometimes we can use Cantor encoding to encode this triple still further. At other times, all we actually need is ax, because b will be known and need not be included in the code, while n may not matter. In that case, we also call ax itself a positional code, when the context makes the meaning clear. One further point: an advantage of positional encoding is that if n is larger than the length of the original code, decoding merely produces additional trailing 0, and in many situations we do not care about extra 0.
Its coordinate function is likewise Diophantine, but using radix notation has a drawback: we must introduce something more powerful. Let Elem(a,b,d) denote the value at position d, so
e=Elem(a,b,d)⇔∃xy(a=xbd+ebd−1+y & e<b & y<bd−1 & d>0)
Did you notice the “more powerful” ingredient we introduced? We used an exponential function such as bd, which we have not yet proved to be Diophantine. As the historical account showed, this is in fact a very difficult part of the proof. For now, we assume that exponentiation is a Diophantine function; a proof may be supplied in the next article.
It follows that Elem(a,b,d) is also a Diophantine function. But recall that we introduced this encoding to perform more complex operations. For example, componentwise addition: we need only add the positional codes directly, provided the result in every position does not exceed b; for positional encoding, this is nearly trivial.
Now consider another operation: concatenation Cat. Let there be another tuple (y1,...,ym), which we want to append to (x1,...,xn) to form (x1,...,xn,y1,...,ym). If (y1,...,ym) also has an upper bound b, it too may be represented positionally by (ay,b,m). The positional code of the concatenated tuple a is easy to calculate. Readers can verify that the following relation holds exactly when the values a,b,c form the positional code of the concatenation:
Cat(ax,bx,n,ay,by,m,a,b,c)⇔bx=by=b & c=n+m & a=ax+aybn
Strictly speaking, we must also use & to conjoin two further conditions: (ax,bx,n) and (ay,by,m) must indeed be valid positional codes. Unlike Cantor encoding, positional encoding need not be a bijection, so invalid cases may occur. The validity relation Pos(a,b,n) is also Diophantine, because
Pos(a,b,n)⇔b≥2 & a<bn
Again, this requires assuming that exponentiation is a Diophantine function.
Encoding Turing-Machine Configurations
With positional encoding in hand, we can return to the unfinished task of encoding Turing-machine configurations. As noted above, a configuration contains three pieces of information: the string on the tape, the head position, and the current state. In fact, these can be summarized by two tuples. The first tuple (0,...,0,i,0,...,0) simultaneously records the tape head’s position and the machine’s current state qi, while the second tuple (s1,...,sl) records the string currently on the tape. Both tuples have length l.
More importantly, the entries of both tuples are bounded. An entry of the first tuple cannot exceed the number of states ∣Q∣, while an entry of the second cannot exceed the size of the alphabet ∣Σ∣. We therefore choose a fixed base β>max{∣Q∣,∣Σ∣}, use positional encoding to encode the first tuple as (p,β,l), and encode the second as (t,β,l).
Since β is constant, l is their common length—and, as we will see, we scarcely need it—so we directly regard p,t as the encoding of the Turing-machine configuration. For convenience, we also use p,t to refer to the two tuples themselves.
Diophantine Functions for One Step of a Turing Machine
The preliminaries are complete: we have nearly all the parts, and it is time to assemble them. Our first goal in this section is to construct the Diophantine functions NextP(p,t) and NextT(p,t); respectively, they give the two components of the code for the configuration obtained from p,t by one step. We will later use them to construct AfterP(k,p,t) and AfterT(k,p,t); these Diophantine functions represent the codes of the configurations obtained from p,t after k steps of execution.
We begin with NextT(p,t); the idea is relatively simple. Consider what must be done: from the tuple p=(0,...,0,i,0,...,0),t=(s1,...,sl) we must produce a new tuple t′=(s1′,...,sl′), in which, at every position where p takes 0 in the original tuple, we simply copy the value of t into t′; at the position where it takes i—the position of the tape head—the corresponding symbol must be changed. This is exactly what our existing Turing-machine function Σ(i,j) does, because Σ(i,j) leaves the symbol unchanged when i=0, returning j; otherwise it returns the modified symbol. In fact, this requirement is precisely why we designed Σ(i,j).
But Σ handles only a single position, whereas we want to process an entire tuple. We therefore need some syntactic sugar that extends a function from one entry to a variable-length tuple, applying the function to every entry. This should be easy to understand, since such syntactic sugar is common in modern programming languages.
In general, consider a Diophantine function f(x), and assume that every entry of the tuples below is less than b. We wish to construct a Diophantine function fb(a,c), which maps the positional code (a,b,c) of the tuple (a1,...,ac) to the tuple (f(a1),...,f(ac)); its positional code is (fb(a,c),b,c). When (a,b,c) is not a valid code, fb(a,c) may be assigned arbitrarily.
This construction requires some care and is slightly laborious. I will give its outline and leave the proof to you. The key idea is this: because b is a fixed finite bound, we enumerate its possible values and decompose the tuple into a collection of 0–1 indicator vectors.
Specifically, let hi(i=0,...,b−1) be the positional code of the vector (hi,1,...,hi,c), where hi,j indicates whether aj=i: it takes the value 1 when the equality holds and 0 otherwise. In other words, hi records the positions at which a takes the value i.
Recall that positional codes can be added directly. Thus, observe that
0⋅h0+1⋅h1+⋯+(b−1)⋅hb−1=a
Also observe that
f(0)⋅h0+f(1)⋅h1+⋯+f(b−1)⋅hb−1=fb(a,c)
It therefore suffices to show that hi are vectors determined by Diophantine functions and relations; this will establish that fb(a,c) is a Diophantine function.
Define the function Repeat(x,b,c) as the positional code of the tuple (x,x,...,x) (x<b), with c entries, in base b. Define the relation Orthb(x1,x2,c) to mean that the tuples encoded by (x1,b,c) and (x2,b,c) are 01 indicator vectors that are mutually disjoint: two 1 values never occur at the same position. You can verify that both are Diophantine. These two Diophantine relations, together with the preceding equation—which is itself essentially a Diophantine relation because b is constant—uniquely determine all the hi. This shows that fb(a,c) is a Diophantine function. Notice that this uses the earlier idea: we do not write down h directly, but instead use relations such as Repeat to constrain h, ensuring that a qualifying h exists and is unique; we then use the existential quantifier ∃ to select it.
More generally, this construction extends to multivariable functions f(x1,...,xn), yielding fb(a1,...,an,c), because we still need only a finite enumeration. This is precisely what we wanted.
Returning to our construction of NextT(p,t), this syntactic sugar completes it:
t′=NextT(p,t)⇔∃w(t′=Σβ(p,t,w))
Here w serves as the tuple length. Readers may notice that when w>l, p,t can still be decoded. Could this produce an incorrect t′? No, because it merely produces extra 0s; after the Σ mapping, they remain 0s, so they do not affect the value of t′. The reason we must proceed this way is that l changes as the Turing machine runs, making it difficult and unnecessary to maintain a changing l. Instead, we rely only on the existence of l and the useful property that “redundant 0 entries do not change a positional code.”
We have thus obtained NextT. Although the construction is lengthy, its idea is not complicated. Next comes NextP(p,t), whose construction is less direct. t changes componentwise, so our syntactic sugar handles it neatly. The Turing machine’s tape head moves left or right, however, which means that the change in p depends on neighboring values.
This obstacle can nevertheless be overcome. A positional code can easily be shifted by multiplying by β or dividing by β! For a base-β positional code a, we use aL=a/β (integer division) to represent a left shift—removing the first entry and appending 0—and use aR=aβ to represent a right shift—making the first entry 0 and shifting every other entry one place to the right.
We can now apply our syntactic sugar to the tuples after shifting them left and right. At the level of a single entry, this amounts to “taking neighboring entries into account.” Specifically, we want to define a function DQ (because it combines the Turing-machine functions D and Q) such that its lifted, componentwise form DQβ gives NextP as follows:
p′=NextP(p,t)⇔∃w(p′=DQβ(pL,p,pR,tL,t,tR,w))
If you already see what we are doing, excellent: spelling out the definition of DQ is genuinely cumbersome. If not, compare it with the explicit definition of DQ and work through it again. We define DQ(ir,i,il,tr,t,tl) as follows. Notice that left and right are reversed here: shifting p left moves the entry on the right into place, so the variable corresponding to pL is denoted ir; the other cases are analogous:
DQ=⎩⎪⎪⎨⎪⎪⎧Q(il,jl)Q(i,j)Q(ir,jr)0il>0,i=ir=0,D(il,jl)=Lil=ir=0,i>0,D(i,j)=−il=i=0,ir>0,D(ir,jr)=Rotherwise
Thus, NextP has been constructed as well.
Diophantine Functions for Multiple Steps of a Turing Machine
The end is in sight. We now prove that AfterP(k,p,t) and AfterT(k,p,t) are also Diophantine functions. They encode the configurations obtained from p,t after k steps of execution.
The evident difficulty is k. We all know that iterating NextP and NextT exactly k times yields the two desired functions, but k is a variable rather than a constant, so this iteration does not establish that the functions are Diophantine.
The solution follows the computation-history idea: consider the entire computation over these k steps—that is, all k+1 configurations—find enough conditions to constrain them, and then select them with existential quantifiers.
Continue to use the aforementioned β as the radix for positional encoding. Let p0=p,t0=t, and let pi,ti(i≤k) be the encoded result after i iterations.
Recall that positional encoding lets us concatenate tuples. To handle these k+1 configurations, we concatenate them. Concatenation requires a specified tuple length, however, while the configuration tuples vary in length. This is not a problem: we can assign a length l greater than every tuple involved. This merely introduces a few trailing 0 upon decoding, and we already know that extra 0 entries cause no error.
Specifically, let (pL,β,kl) be the result of concatenating the positional codes (p0,β,l),(p1,β,l),...,(pk−1,β,l); let (pR,β,kl) be the result of concatenating (p1,β,l),(p2,β,l),...,(pk,β,l) in the same way. We do likewise for tL,tR.
Why define them this way instead of concatenating all k+1 configurations? Because we have the following observation: pR=NextP(pL,tL),tR=NextT(pL,tL). This holds because NextT acts componentwise, so it can operate on several concatenated configurations at once, while NextP is almost componentwise, except that it also examines adjacent entries. We need only insert 0 between configurations to prevent interference, which merely requires taking l sufficiently large.
This observation supplies an important constraint. We can also see that if (pM,β,(k−1)l) denotes the “middle portion,” namely the concatenation of (p1,β,l),...,(pk−1,β,l), and we define tM analogously, then: (pL,β,l) is the concatenation of (p0,β,l) and (pM,β,(k−1)l); while (pR,β,l) is the concatenation of (pM,β,(k−1)l) and (pk,β,l). tL,tR are analogous.
This transformation may look almost trivial, but it makes an essential difference. Now pL is no longer a concatenation of k tuples; it has become a concatenation of just p0 and pM—two tuples—so it is now an operation of a Diophantine function. The same is true of pR,tL,tR. Yet pM,tM remains a concatenation of k−1 tuples. It may seem that we have not really solved the problem, but we have. We can now assert that the relations above uniquely determine pL,tL,pM,tM,pR,tR,pk,tk.
To see this, let us collect the constraints obtained so far (we write +c for tuple concatenation):
pRtR(pL,β,kl)(pR,β,kl)(tL,β,kl)(tR,β,kl)=NextP(pL,tL)=NextT(pL,tL)=(p,β,l)+c(pM,β,(k−1)l)=(pM,β,(k−1)l)+c(pk,β,l)=(t,β,l)+c(tM,β,(k−1)l)=(tM,β,(k−1)l)+c(tk,β,l)
Existence is immediate, because we can in fact run the machine for k steps; only uniqueness remains to be proved. For this purpose, consider the entries represented by pL and the other encoded tuples one by one.
pL has its first l entries equal to p itself, so they are uniquely determined. From pR=NextP(pL,tL) and the decomposition of pR, it follows that pM is determined through its first l−1 entries (because NextP's first l−1 output entries depend only on the first l input entries). Once pM has been determined through its first l−1 entries, the decomposition of pL determines 2l−1 entries, and so on. Repeating this argument determines pL,pM in full.
A careful reader may spot a remaining issue: the last entry of pR has not yet been determined. This is because NextP determines an output one entry shorter than its input. Recall, however, that we made l slightly larger, so the last entry of pR is actually 0. This determines pR,pk as well. The argument for tL,tR,tM,tk is exactly analogous—and even simpler.
This is equivalent to saying that pk=AfterP(k,p,t) and tk=AfterT(k,p,t) are Diophantine functions. If you insist on writing the definition explicitly, it requires only a large collection of existential quantifiers: there exists a sufficiently large l, there exist pL,pM,... and all the other variables above, and the listed conditions are joined by logical conjunction. This completes the final part.
Hilbert’s Tenth Problem Is Unsolvable
Everything now falls into place. Given a Turing machine M and its corresponding recursively enumerable set S, define the Diophantine functions as above. Then (a1,...,an)∈S holds if and only if:
∃krpt(Elem(AfterP(k,p,t),β,r)=∣Q∣ & p=1 & t=i=1∑naiβi−1)
Let us unpack these three conditions. Elem(AfterP(k,p,t),β,r) says that after k steps, the Turing-machine head is at position r, and the current state is q∣Q∣ (the final state). p=1 is the index of the initial state q1, so (1,0,...) is the code of this tuple, representing the machine’s initial head position and state. t=∑i=1naiβi−1 is the encoding of the machine’s initial input. Notice that n is a fixed constant, so this sum is a valid operation. Together, the conditions say that the Turing machine, on input (a1,...,an), halts after k steps.
All three conditions are Diophantine, establishing that S is a Diophantine set. We have therefore proved the MRDP theorem:
Diophantine sets are precisely the recursively enumerable sets.
We already know that some recursively enumerable sets are not recursive—for example, the recursively enumerable set associated with the halting problem. The process above is entirely constructive. Thus, in principle, given a Turing machine corresponding to such a recursively enumerable set, we can explicitly write down the variables and coefficients of a family of Diophantine equations corresponding to that set. The existence of integer solutions for this family must be undecidable; otherwise, the set itself would be decidable.
If solvability is undecidable even for a subclass of Diophantine equations—and we can explicitly provide their variables and coefficients, so there is no obstacle of encoding conversion—then solvability for all Diophantine equations is certainly undecidable. We may therefore conclude: Hilbert’s Tenth Problem is unsolvable.
(\Finished—time to celebrate!/)

