## 1 Introduction

In his invited paper [1] at The First International Conference on Unifying Theories of Programming, Eric Hehner dedicates a section to the proof of the halting problem, claiming that it entails an unstated assumption. He agrees that the halt test program cannot exist, but concludes that this is due to an inconsistency in its specification. Hehner has republished his arguments using less formal notation in [2].

The halting problem is considered to be an essential part of the theoretical background to computing. That halting is not in general computable has been “proved” in many text books and taught on many computer science courses to illustrate the limits of computation. Hehner’s claim is therefore extraordinary. Nevertheless he is an eminent and highly creative computer scientist whose opinions reward careful attention. In judging Hehner’s thesis we take the view that to illustrate the limits of computation we need a consistent specification which cannot be implemented.

For our discussion we use a guarded command language for sequential state based programs. Our language includes named procedures and named enquiries and tests. These constructs may have input parameters. Enquiries and tests allow assignment only to their own local variables; they are thus side effect free. They are used in expressions, where they represent the value returned by the enquiry. Procedures must be invoked as program statements.

With the text of each program we associate a unique number , known as the program’s encoding, which will stand for the program when we want to use that program as data, e.g. when passing one program to another as an argument.

The halting problem is typically stated as follows. Given a Turing machine equivalent (TME) language there is no halt test program

which will tell us, for arbitrary program and data , whether will halt when applied to .Hehner simplifies this, saying there is no need to consider a program applied to data, as data passed to a program could always be incorporated within the program. So his version is that there is no halt test which tells us, for an arbitrary program , whether execution of will halt.

Where context allows us to distinguish from , we may allow ourselves to write instead of . For example we will write and etc rather than , .

The proof that cannot be implemented goes as follows. Under the assumption that we have implemented , and that we have a program which is a non-terminating loop, we ask whether the following program will halt:

Now within , must halt and provide a true or false judgement for the halting of . If it judges that will halt, then will enter a non-terminating Loop. If it judges that will not halt, then will halt.

Since cannot pass a correct judgement for , we must withdraw our assumption that there is an implementation of . Thus halting behaviour cannot, in general, be computed.

In this paper we will not be satisfied with this proof and will look in more detail at the specification of . If we can specify there will be some interest in proving it is not implementable. If we cannot specify it we have a problem: we won’t be able to say formally what it is that cannot be implemented.

The paper is structured as follows. In section 2 we verify Hehner’s simplification of the halting problem. In section 3 we make some general remarks on unbounded memory calculations and connections between halt tests and mathematical proofs. We also show that failure to halt is observable for computations with fixed memory resources. In section 4 we consider a halt test that is required to work only for a small set of stateless programs, and we find we can still use the same proof that we cannot have a halt test. We examine the specification of the halt test for this limited scenario in detail, and we describe an implementation of an amended halt test that is allowed to report non-halting by an error message if the test itself cannot terminate. In section 5 we perform a semantic analysis of , taking its definition as a recursive equation, and conclude that its defining equation has no solution. does not exist as a conceptual object, and neither does our putative halt test .

The halting problem is generally attributed to Turing’s paper on Computable Numbers [3], but the connection is slightly less direct than this implies. In an appendix we briefly describe Turing’s paper and how the halting problem emerged from it. We give an example, from Turing’s paper, of an uncomputable function which has a consistent specification.

## 2 Hehner’s simplification of the halting problem

Normally the halting problem is discussed in terms of a halt test taking data and program and reporting whether halts when applied to .

Hehner’s simplified halt test takes a program and reports whether it halts.

We refer to the first of these halt tests as , since it takes two arguments, and the second as .

To verify Hehner’s simplification of the halting problem we show that any test that can be performed by can also be performed by , and any test that can be performed by can also be performed by .

Proof Given procedures and , and tests and where reports whether halts, and reports whether halts:

then if we define an operation the test can be performed using as .

and if we define an operation , where the name is chosen to be non-free in , the test can be performed by as .

## 3 Some notes on halting analysis

Fermat’s last theorem states that for any integer there are no integers such that:

Since 1995, when Andrew Wiles produced a proof 150 pages long, the theorem is recognised as true.

Given a program which searches exhaustively for a counter example and halts when it finds one, and a halt test we could have proved the theorem by executing the test This would tell us the program does not halt, implying that the search for a counter example will continue forever, in other words that no counter example exists and the theorem is therefore true.

The Goldbach conjecture, which states that every even integer can be expressed as the sum of two primes (we include 1 in the prime numbers). This is an unproved conjecture, but so far no counter example has been found, although it has been checked for all numbers up to and somewhat beyond . Given a program which searches exhaustively for a solution to the Goldbach conjecture and terminates if it finds one, and halt test for , we could decide the truth of the conjecture by executing the test .

The programs and would have unbounded memory requirements, as they must be able to deal with increasingly large integers.

When considering the halting problem we normally assume idealised computers with unbounded memory. But suppose we have a program that is to be run on a computer with bits of memory. Its state transitions can take it to at most different states. We can solve the halting problem for this program by providing an additional bits of memory and using this as a counter. When we have counted state transitions and the program has not halted, we know it will never halt because it must have, at some point, revisited a previous state.

Of course the question being answered by the proof, on the one hand, and the monitoring of execution, on the other, are not the same. Monitoring execution does not require the “twisted self reference” (Hehner’s term) that occurs in our proposed program . There is a separation between the monitor, as observer, and the executing program, as the thing observed.

## 4 A halt test for a limited set of programs

The conventional view of the halting problem proof is that it shows a universal halt test is impossible in a TME language. In this section we seek to clarify the inconsistency of the halt test specification by limiting our discussions to a small set of state free programs.

Consider first the set

is a set for which we can specify a halt test . The specification is consistent because it has a model:

Now we become ambitious and wish to consider the set:

, with a halt test .

Our definition of is still:

and our specification for is:

For , is true if execution of halts, and false otherwise.

But what is the model for ?

Our model must map to either true or false, but whichever is chosen will be wrong. We have no model for , so it cannot have a consistent specification.

We have reduced the halting problem to this limited scenario so we can attempt to write out the model of halting, but exactly the same argument applies to halting in a TME language.

In this limited scenario we can make the same “proof” that halting is uncomputable that we used for TME languages in the introduction.

### 4.1 Experiments with code

Setting aside formal analysis for a moment, let us see what our programming intuition can tell us about the strange program

.

And let us see if we can tweak so that can actually be implemented.

Although the halt test is unable to tell us this, looks as if it will NOT terminate, because when is executed within , it will be faced with again deciding the result of with no additional information to help it. will not terminate, but this is because the halt test invoked within it cannot terminate.

There is no reason, however, why the halt test cannot terminate in other situations, or why failure to halt cannot be reported via an error message when the halt test itself cannot halt.

We now consider a halt test for use with the set

where:

For , returns a true flag if execution of halts. If execution of does not halt return a false flag, unless has been invoked within , in which case report an error.

Here is the error report when is invoked.

Implementation of requires it to determine whether it is being invoked from within . In a typical compiled sequential language this information can be deduced from the return address for the call to , and the symbol table, which contains information that will tell us whether this return address is within the code body of . However, this information is not usually directly accessible in the language, so we will suppose we have written at assembly code level a test which will report whether the operation that invokes it has been invoked from within .

We also assume an error handler which is invoked when an error condition is detected. It prints the string as an error message, and handles the error. Formally this a form of non-termination.

In defining we build into it the conclusions we deduced above: does not terminate, but cannot report this in the normal way if it has been invoked from within .

This illustrates that the problem is not that halting of cannot be computed, but that the result cannot always be communicated in the specified way. Requiring (or in this case ) to halt in all cases is too strong, as it may be the halt test itself that cannot halt.

## 5 Proof and paradox

In [1] the halting problem is compared to the Barber’s paradox. “The barber, who is a man, shaves all and only the men in the village who do not shave themselves. Who shaves the barber?” If we assume he shaves himself, we see we must be wrong, because the barber shaves only men who do not shave themselves. If we assume he does not shave himself, we again see we must be wrong, because the barber shaves all men who do not shave themselves. The statement of the paradox seems to tell us something about the village, but it does not, since conceptually no such village can exist.

In a similar way, the program which we have used in the halting problem proof, does not exist as a conceptual object so what we say about it can be paradoxical.

To argue this formally we use the following termination rule:

(1)

And we specify the result of applying to program as:

Bearing in mind that is true by the specification of , we argue:

So we have proved that . This tells us that does not exist as a conceptual object, let alone as a program. We have seen in the previous section that by relaxing the specification of we can implement the same textual definition of , so the non existence of proved here can only be due to the specification of being inconsistent.

The proof of the halting problem assumes a universal halt test exists and then provides as an example of a program that the test cannot handle. But is not a program at all. It is not even a conceptual object, and this is due to inconsistencies in the specification of the halting function. also doesn’t exist as a conceptual object, and we have already seen this from a previous argument where we show it has no model.

## 6 Conclusions

The idea of a universal halting test seems reasonable, but cannot be formalised as a consistent specification. It has no model and does not exist as a conceptual object. Assuming its conceptual existence leads to a paradox.

The halting problem is universally used in university courses on Computer Science to illustrate the limits of computation. Hehner claims the halting problem is misconceived. Presented with a claim that a universal halt test cannot be implemented we might ask – what is the specification of this test that cannot be implemented? The informal answer, that there is no program which can be used to test the halting behaviour of an arbitrary program, cannot be formalised as a consistent specification.

The program , used as example of a program whose halting cannot be analysed, observes its own halting behaviour and does the opposite. Hehner calls this a “twisted self reference”. It violates the key scientific principle of, where possible, keeping what we are observing free from the effects of the observation.

To better understand Hehner’s thesis we have verified his simplification of the halting problem, and studied a set of three stateless programs and a halt test, to which exactly the same proof can be applied.

Our programming intuition tells us that will not terminate because when is invoked within , will not terminate. However, we cannot require to return a value to report this, because that would require it to terminate! We provide a programming example based on a a halt test for a small set of programs, where we resolve this by allowing the option for the halt test to report via an error message when it finds itself in this situation. However, we can require that the halt test should always halt in other situations. The problem, in our little scenario for which the halting problem proof can still be applied, is not the uncomputability of halting!

We have also performed a semantic analysis which confirms that the halt test and do not exist as conceptual objects.

Having a halt test for specific unbounded memory computations, such as those that search for counter examples to Fermat’s last theorem and the Goldbach conjecture, involves no inconsistency, and would give us enormous mathematical powers, but this has nothing to do with the halting paradox.

We have found nothing to make us disagree with Hehner’s analysis. Defenders of the status quo might say – so the halt test can’t even be conceived, so it doesn’t exist. What’s the difference? Hehner says that uncomputability should refer to what can be defined (specified) but not implemented. Turing’s uncomputable sequence provides such an example, and is discussed in the appendix.

Acknowledgements.

Thanks to Ric Hehner for extensive electronic conversations and to Steve Dunne for extended discussions.

## References

- [1] E C R Hehner. Retrospective and Prospective for Unifying Theories of Programming. In S E Dunne and W Stoddart, editors, UTP2006 The First International Symposium on Unifying Theories of Programming, number 4010 in Lecture Notes in Computer Science, 2006.
- [2] E C R Hehner. Problems with the halting problem. Advances in Computer Science and Engineering, 10(1):31–60, 2013. See www.cs.utoronto.ca/ hehner/halting.html.
- [3] Alan M Turing. On computable numbers, with an application to the Entscheidungsproblem. Proceedings of the London Mathematical Society, 2(42):230–265, 1936.