In computer science, a termination analysis is program analysis which attempts to determine whether the evaluation of a given program will definitely terminate. Because the halting problem is undecidable, termination analysis cannot be total. The aim is to find the answer "program does terminate" (or "program does not terminate") whenever this is possible. Without success the algorithm (or human) working on the termination analysis may answer with "maybe" or continue working infinitely long.
A simple, general method for constructing termination proofs involves associating a measure with each step of an algorithm. The measure is taken from the domain of a well-founded relation, such as from the ordinal numbers. If the measure "decreases" according to the relation along every possible step of the algorithm, it must terminate, because there are no infinite descending chains with respect to a well-founded relation.
Some types of termination analysis can automatically generate or imply the existence of a termination proof.
An example of a programming language construct which may or may not terminate is a loop, as they can be run repeatedly. Loops implemented using a counter variable as typically found in data processing algorithms will usually terminate, demonstrated by the pseudocode example below:
i := 0 loop until i = SIZE_OF_DATA process_data(data[i])) //process the data chunk at position i i := i + 1 //move to the next chunk of data to be processed
If the value of SIZE_OF_DATA is non-negative, fixed and finite, the loop will eventually terminate, assuming process_data terminates too.
Some loops can be shown to always terminate or never terminate, through human inspection. For example, even a non-programmer should see that, in theory, the following never stops (but it may halt on physical machines due to arithmetic overflow):
i := 1 loop until i = 0 i := i + 1
In termination analysis one may also try to determine the termination behaviour of some program depending on some unknown input. The following example illustrates this problem.
i := 1 loop until i = UNKNOWN i := i + 1
Here the loop condition is defined using some value UNKNOWN, where the value of UNKNOWN is not known (e.g. defined by the user's input when the program is executed). Here the termination analysis must take into account all possible values of UNKNOWN and find out that in the possible case of UNKNOWN = 0 (as in the original example) the termination cannot be shown.
There is, however, no general procedure for determining whether an expression involving looping instructions will halt, even when humans are tasked with the inspection. The theoretical reason for this is the undecidability of the Halting Problem: there cannot exist some algorithm which determines whether any given program stops after finitely many computation steps.
In practice one fails to show termination (or non-termination) because every algorithm works with a finite set of methods being able to extract relevant information out of a given program. A method might look at how variables change with respect to some loop condition (possibly showing termination for that loop), other methods might try to transform the program's calculation to some mathematical construct and work on that, possibly getting information about the termination behaviour out of some properties of this mathematical model. But because each method is only able to "see" some specific reasons for (non)termination, even through combination of such methods one cannot cover all possible reasons for (non)termination.
Recursive functions and loops are equivalent in expression; any expression involving loops can be written using recursion, and vice versa. Thus the termination of recursive expressions is also undecidable in general. Most recursive expressions found in common usage (i.e. not pathological) can be shown to terminate through various means, usually depending on the definition of the expression itself. As an example, the function argument in the recursive expression for the factorial function below will always decrease by 1; from the well-ordering property on natural numbers, the argument will eventually reach 1 and the recursion will terminate.
function factorial (argument as natural number) if argument = 0 or argument = 1 return 1 otherwise return argument * factorial(argument - 1)
Termination check is very important in dependently typed programming language and theorem proving systems like Coq and Agda. These systems use Curry-Howard isomorphism between programs and proofs. Proofs over inductively defined data types were traditionally described using induction and recursion principles which are in fact, primitive recursion. However, it was found later, that describing a program via a recursively defined function with pattern matching is more natural way of proving than using induction principle directly. Unfortunately, allowing arbitrary, including non terminating definitions, leads to possibility of logical inconsistencies in type theories. That's why Agda and Coq have termination checkers built-in.
One of the approaches to termination checking in dependently typed programming languages are sized types. The main idea is to annotate the types over which we can recurse with size annotations and allow recursive calls only on smaller arguments. Sized types are implemented in Agda as a syntactic extension.
There are several research teams that work on new methods that can show (non)termination. Many researchers include these methods into programs that try to analyze the termination behavior automatically (so without human interaction). An on-going aspect of research is to allow the existing methods to be used to analyze termination behavior of programs written in "real world" programming languages. For declarative languages like Haskell, Mercury and Prolog, many results exist (mainly because of the strong mathematical background of these languages). The research community also works on new methods to analyze termination behavior of programs written in imperative languages like C and Java.
Because of the undecidability of the Halting Problem research in this field cannot reach completeness. One can always think of new methods that find new (complicated) reasons for termination.
- Complexity analysis — the problem of estimating the time needed to terminate
- Loop variant
- Total functional programming — a programming paradigm that restricts the range of programs to those that are provably terminating
- Walther recursion
- Tools at termination-portal.org
- Giesl, J. and Swiderski, S. and Schneider-Kamp, P. and Thiemann, R. Pfenning, F., ed. "Term Rewriting and Applications, 17th Int. Conf., RTA-06" (postscript). LNCS 4098. pp. 297–312.
- Compiler options for termination analysis in Mercury
Research papers on automated program termination analysis include:
- Christoph Walther (1988). "Argument-Bounded Algorithms as a Basis for Automated Termination Proofs". Proc. 9th Conference on Automated Deduction. LNAI 310. Springer. pp. 602–621.
- Christoph Walther (1991). "On Proving the Termination of Algorithms by Machine". Artificial Intelligence 70 (1).
- Xi, Hongwei (1998). "Towards Automated Termination Proofs through Freezing". In Tobias Nipkow. [[Rewriting Techniques and Applications]], 9th Int. Conf., RTA-98. LNCS 1379. Springer. pp. 271–285. Wikilink embedded in URL title (help)
- Jürgen Giesl; Christoph Walther; Jürgen Brauburger (1998). "Termination Analysis for Functional Programs". In W. Bibel; P. Schmitt. Automated Deduction - A Basis for Applications (postscript) 3. Dordrecht: Kluwer Academic Publishers. pp. 135–164.
- Christoph Walther (2000). "Criteria for Termination". In S. Hölldobler. Intellectics and Computational Logic (postscript). Dordrecht: Kluwer Academic Publishers. pp. 361–386.
- Christoph Walther; Stephan Schweitzer (2005). "Automated Termination Analysis for Incompletely Defined Programs". In Franz Baader; Andrei Voronkov. Proc. 11th Int. Conf. on [[Logic for Programming, Artificial Intelligence and Reasoning]] (LPAR). LNAI 3452. Springer. pp. 332–346. Wikilink embedded in URL title (help)
- Adam Koprowski; Johannes Waldmann (2008). "Arctic Termination ...Below Zero". In Andrei Voronkov. Rewriting Techniques and Applications, 19th Int. Conf., RTA-08. Lecture Notes in Computer Science 5117. Springer. pp. 202–216. ISBN 978-3-540-70588-8.
System descriptions of automated termination analysis tools include:
- Giesl, J. (1995). "Generating Polynomial Orderings for Termination Proofs (system description)". In Hsiang, Jieh. Rewriting Techniques and Applications, 6th Int. Conf., RTA-95 (postscript). LNCS 914. Springer. pp. 426–431.
- Ohlebusch, E.; Claves, C.; Marché, C. (2000). "TALP: A Tool for the Termination Analysis of Logic Programs (system description)". In Bachmair, Leo. Rewriting Techniques and Applications, 11th Int. Conf., RTA-00 (compressed postscript). LNCS 1833. Springer. pp. 270–273.
- Hirokawa, N.; Middeldorp, A. (2003). "Tsukuba Termination Tool (system description)". In Nieuwenhuis, R. Rewriting Techniques and Applications, 14th Int. Conf., RTA-03. LNCS 2706. Springer. pp. 311–320.
- Giesl, J.; Thiemann, R.; Schneider-Kamp, P.; Falke, S. (2004). "Automated Termination Proofs with AProVE (system description)". In van Oostrom, V. Rewriting Techniques and Applications, 15th Int. Conf., RTA-04. LNCS 3091. Springer. pp. 210–220. ISBN 3-540-22153-0.
- Hirokawa, N.; Middeldorp, A. (2005). "Tyrolean Termination Tool (system description)". In Giesl, J. Term Rewriting and Applications, 16th Int. Conf., RTA-05. LNCS 3467. Springer. pp. 175–184. ISBN 978-3-540-25596-3.
- Koprowski, A. (2006). "TPA: Termination Proved Automatically (system description)". In Pfenning, F. Term Rewriting and Applications, 17th Int. Conf., RTA-06. LNCS 4098. Springer. pp. 257–266.
- Marché, C.; Zantema, H. (2007). "The Termination Competition (system description)". In Baader, F. Term Rewriting and Applications, 18th Int. Conf., RTA-07. LNCS 4533. Springer. pp. 303–313.
- Termination Analysis of Higher-Order Functional Programs
- Termination Tools mailing list
- Termination Competition — see Marché, Zantema (2007) for a description
- Termination Portal