This paper was converted on www.awesomepapers.org from LaTeX by an anonymous user.
Want to know more? Visit the Converter page.

\jdate

July 2020 \pagerangeCoinduction Plain and SimpleLABEL:lastpage

Coinduction Plain and Simple

FRANÇOIS BRY
Institute for Informatics
   Ludwig-Maximilian University of Munich    Germany
bry@lmu.de
Abstract

Coinduction refers to both a technique for the definition of infinite streams, so-called codata, and a technique for proving the equality of coinductively specified codata. This article first reviews coinduction in declarative programming. Second, it reviews and slightly extends the formalism commonly used for specifying codata. Third, it generalizes the coinduction proof principle, which has been originally specified for the equality predicate only, to other predicates. This generalization makes the coinduction proof principle more intuitive and stresses its closeness with structural induction. The article finally suggests in its conclusion extensions of functional and logic programming with limited and decidable forms of the generalized coinduction proof principle.

doi:
S1471068401001193
keywords:
Theory of computation, Semantics and reasoning, Programming logic

1 Introduction

A data stream, short stream, is a possibly never ending sequence of data. A stream is observed when its data result from observations or measurements of natural or artificial systems. An observed data stream might for example convey temperatures, the reproduction rates of a disease, or energy consumption or traffic volumes. A stream is constructed when its data are synthetic. Constructed streams are useful as encoded models of observed streams. Using streams, an early detection of critical situations can be specified as the continuous comparison of the data of an observed stream with that of a constructed stream modelling some behavior.

Constructed streams are finitely defined from non-stream data and operations on such data. Thus, two disjoint data types are considered in the following: Non-stream data the type of which is called data and stream data the type of which is called codata.

Constructed streams, or codata, are finitely defined for, otherwise, they could not be used in programming. Codata express repetitions by recursion. As a consequence, recursive functions like the Fibonacci function can be expressed as codata. The specification of recursive functions as codata is interesting in its own right, independently of stream-related applications, because recursive codata yield iterative computation processes like tail recursive functions do but without the recourse to accumulators.

Streams are related to processes. An observation process operating on an observed stream might be unpredictable, or only partly predictable, while a process operating on a constructed stream, even though it might never end, can be given a finite definition derived from that of the constructed stream it refers to. Coinduction in declarative programming has been used for the specification of both constructed streams and processes operating on constructed streams.

This article first reviews coinduction in declarative programming. Second, it reviews and slightly extends the formalism commonly used for specifying codata. Third, it generalizes the coinduction proof principle to other predicates than equality. The article finally suggests in its conclusion extensions of functional and logic programming with limited and decidable forms of the generalized coinduction proof principle.

2 Coinduction in Declarative Programming

Coinduction was introduced in 1971 by Robin Milner in an investigation of the correctness of terminating or non-terminating imperative programs [Milner (1971)]. More precisely, the article [Milner (1971)] introduced simulation relations and a precursor of the coinductive proof principle consisting in exhibiting finitely many pairs of related states and verifying that a simulation relation holds of each pair. David Park defined in 1981 bisimilarity as a greatest fixpoint, derived from fixpoint theory the bisimulation proof method [Park (1981)] which is now also called coinductive proof principle. Bisimulation and the coinductive proof principle soon became cornerstones of process algebra [Hoare (1978), Fokkink (2007)] and of the theory of communicating concurrent processes [Milner (1980)]. Davide Sangiorgi gives in [Sangiorgi (2009)] an extensive account of the origins of coinduction, bisimulation and of related precursor concepts and methods in philosophical and mathematical logic, mathematics and computer science which, however, does not address coinduction in declarative programming and does not mention inductionless induction [Comon (2006)].

Coinductive definitions, or codata, have been introduced in 1982 by Alain Colmerauer in logic programming under the name of rational trees [Colmerauer (1982)], “tree” meaning finite or infinite term. A rational tree is a finite or infinite tree the set of subtrees of which is finite. The name “rational tree” which, puzzlingly, is not explained in [Colmerauer (1982), Colmerauer (1984)], was chosen in reference to the fact that a real number is a rational number if and only if its decimal expansion is finite or repeating [Colmerauer (1988)]. The name “rational tree” appropriately stresses that, by Georg Cantor’s diagonal argument [Cantor (1891)], the set of (rational and non-rational) trees over a finite or denumerable alphabet is not denumerable111This fact challenges model theories for logic programming with observed streams. while the set of rational trees of course is denumerable.

Following Courcelle [Courcelle (1983)], rational trees are also named regular trees. In the 1980s rational trees were easily expressed in Prolog because, for efficiency reasons at a time processors were slow, Prolog did not perform the occurs-check during unification: An infinite list of 11s could for example be finitely expressed as X = [1|X] or, redundantly, as X = [1,1,1|X] and an infinite list of alternating 0s and 11s as X = [0,1|X]. Colmerauer systematized this observation and designed a variant of Prolog, Prolog II [Colmerauer (1984), van Emden and Lloyd (1984)], which supported rational trees. Michael Maher gave in 1988 in [Maher (1988)] an axiomatization of the algebras of rational trees. Unification algorithms for rational trees were proposed in [Mukai (1983), Jaffar (1984), Martelli and Rossi (1984)]. A meta-interpreter for a logic programming language supporting rational (or regular) trees (or terms) is described in [Ancona (2013)].222The article does not clarify in which cases unification is performed with, respectively without, occurs-checks.

Coinductive definitions in logic programming are possible not only with rational trees defined using unification without occurs-check, but also through non-terminating SLD derivations based on unification with occurs-check. This approach has been first investigated in 1983 by Nait Abdallah in [Abdallah (1983)], further investigated in [Abdallah (1984), van Emden and Abdallah (1985), Palamidessi et al. (1985)]333The “completion of a program” mentioned in [van Emden and Abdallah (1985)] is Clark’s completion semantics of negation in logic programming [Clark (1978)]. Thus, it is not related to the metric-based completion of the Herbrand universe introduced in [Abdallah (1983)]. and popularized in 1987 by John Lloyd with the chapter on perpetual processes of the second edition of his Foundations of Logic Programming [Lloyd (1987)]. Each stage of a non-terminating SLD derivation like that resulting from the evaluation of ?- p(Y). against the clause p(X) :- p(f(X)). is seen as a finite approximation of an atom containing an infinite term f(f(f(...))). Nait Abdallah formalized such infinite terms as follows.

The Herbrand universe HH is first equipped with a metric:

d(t1,t2)d(t_{1},t_{2}) == 0 if t1=t2t_{1}=t_{2}
d(t1,t2)d(t_{1},t_{2}) == 2inf{n|an(t1)an(t2)}2^{-\text{inf}\{n|a_{n}(t_{1}){\neq}a_{n}(t_{2})\}} otherwise

where an(t)a_{n}(t) is the “cut at depth n” of a term tt. Thus, inf{n|an(t1)an(t2)}\text{inf}\{n|a_{n}(t_{1})\neq a_{n}(t_{2})\} is the smallest depth at which t1t_{1} and t2t_{2} differ. Using this metric, Cauchy sequences of elements of HH are defined,444A Cauchy sequence is such that the distance between two successive elements tends to zero when the rank tends to infinity. the standard equivalence relation on Cauchy sequences is considered,555Two Cauchy sequences are equivalent if the difference between their elements of same ranks tends to zero when the rank tends to infinity. and the complete Herbrand universe H¯\overline{H} is defined as the set of equivalence classes of Cauchy sequences of elements of HH. Thus, HH¯H\subset\overline{H}.666Like ¯=\mathbb{Q}\subset\overline{\mathbb{Q}}=\mathbb{R}. It is then observed that, by a result of [Mycielski and Taylor (1976)], H¯\overline{H} is compact 777The compactness of H¯\overline{H} means that every Cauchy sequence of elements of H¯\overline{H} has a limit in H¯\overline{H}. if its terms are defined from finitely many symbols. This is the case of the ground (or closed) terms of H¯\overline{H} because programs are finite. Thus, an infinite sequence of elements of HH like for example fn(a)f^{n}(a) has a limit in H¯\overline{H} which is denoted f(f())f(f(\ldots)) or f(ω)f(\omega).

The complete Herbrand base B¯\overline{B} is defined as the set of ground atoms built from terms in the complete Herbrand universe H¯\overline{H}, an immediate consequence operator TT^{\prime} is defined in reference to the complete Herbrand base B¯\overline{B} in the same manner as the standard immediate consequence operator TT is defined in reference to the Herbrand base BB [van Emden and Kowalsi (1976)]. The greatest fixpoint semantics of a definite (that is, negation-free) logic program is defined as the greatest fixpoint of TT^{\prime} for that program. The greatest fixpoint semantics of logic programs is extended to programs with negation in [Jaffar and Stuckey (1986), Hein (1992)]. Refinements of the greatest fixpoint semantics of logic programs are proposed in [Golson (1988), Levi and Palamidessi (1988), Jaume (2002), Ancona et al. (2017), Komendantskaya and Li (2017), Li (2018)].

Some approaches to coinduction in logic programming make use of ancestor subsumption [Socher-Ambrosius (1992)], a technique for avoiding redundant derivations in resolution theorem proving: If a resolvent RR is subsumed (without occurs-check) by one of its ancestors AA, then further derivations from RR can be avoided without compromising completeness. Indeed, if RR is subsumed (without occurs-check) by AA, then every derivation from RR is also possible from AA and therefore redundant.

In the 1980s, as coinductive definitions began to be considered in logic programming, it was folklore knowledge in the community that ancestor subsumption (without occurs-check) can be used for preventing redundant non-terminating SLD derivations (with occurs-check) like in the following examples:888Ancestor subsumption was at the time a commonly considered redundancy elimination technique in resolution theorem proving.

Example 2.1

   p(0).
   allp([H|T]) :- p(H), allp(T).

   ?- X = [0|X], allp(X).
Example 2.2

   p :- p.
   q(X) :- q(X).
   r(f(X)) :- r(f(X)).
   s(X) :- s(f(X)).

   ?- p.
   ?- q(Y).
   ?- r(Y).
   ?- s(Y).
Example 2.3

   member(H, [H|_]).
   member(X, [_|T]) :- member(X, T).

   ?- T = [0|T], member(1, T).

Avoiding redundant derivations by ancestor subsumption (without occurs-check) or any other means does not mean resolving, though, as the examples given above illustrate.

In Example 2.1, X = [0|X] refers to unification without occurs-check and ancestor subsumption avoids that a Prolog system not performing the occurs-check repeatedly proves p(0) and tries to prove allp(X). Without reasoning by induction, the proof of the goal X = [0|X], allp(X) cannot be completed. By induction, it can of course be proved.

In the Example 2.2, ancestor subsumption (without occurs-check) avoids that a Prolog system (performing the occurs-check or not) endlessly attempts to prove p, q(Y), r(f(Y)), and s(f(...f(Y)...)). Even by induction, none of these four goals can be proved.

Example 2.3 is similar to Example 2.2: With ancestor subsumption (without occurs-check), a Prolog system not performing the occurs-check does not endlessly attempt to prove member(1, T). Even by induction, the goal member(1, T) cannot be proved because 1 does not occur in the cyclic list specified by T = [0|T].

Summing up, Examples 2.1, 2.2 and 2.3 illustrate that ancestor subsumption (without occurs-check) [Socher-Ambrosius (1992)] is a pruning rule (that is, a rule for discarding redundant parts of a proof), not an inference rule (that is, a rule for deriving logical consequences).

The downside of ancestor subsumption is its cost what led Rolf Socher-Ambrosius to give in [Socher-Ambrosius (1992)] syntactic characterizations of clause sets giving rise to ancestor subsumption. In [Socher-Ambrosius (1992)] , such clause sets are said to “roughly correspond to sets of logical equivalences”.

Luke Simon, Ajay Bansal, Ajay Mallya and Gopal Gupta proposed in 2006 and 2007 in [Simon et al. (2006), Simon et al. (2007)] coinductive logic programming, a form of logic programming which is the first of its kind for two reasons: First, it combines the two kinds of codata so far proposed for logic programming, rational (or regular) terms like X = [0|X] based on unification without occurs-check, and infinite terms like f(ω\omega) defined as limits of an infinite sequence finite terms constructed during the steps of non-terminating SLDF derivations based, according to the greatest fixpoint semantics of logic programs [Abdallah (1983), Abdallah (1984), van Emden and Abdallah (1985), Lloyd (1987)], on unification with occurs-check. Second, it introduces into logic programming a proof principle named coinductive hypothesis rule which resembles the coinduction proof principle. Applications of coinductive logic programming are presented in [Gupta et al. (2011)]. Implementations of coinductive logic programming languages are described in [Moura (2013), Mantadelis et al. (2014)].

The declarative and operational semantics of coinductive logic programming given in [Simon et al. (2006), Simon et al. (2007)] have confusing aspects. One of them is the claim that coinductive logic programming’s operational semantics is sound and complete with respect to the greatest fixpoint semantics of logic programs [Simon et al. (2006), Simon et al. (2007)]. No explanations are given of how this relates to the downward approximation sequence TpnT_{p}{\downarrow}^{n} of the immediate consequence operator TPT_{P}, the limit of which specifies the greatest fixpoint semantics of a logic program [van Emden and Kowalsi (1976)], not reaching a fixpoint before ω+1\omega+1 with some (finite and definite) programs PP and even not before ω1CK\omega_{1}^{CK} with some others (finite and definite) programs [Fitting (2002), p. 8].999ω\omega is the ordinal defined as the set of all finite ordinals and thus the smallest limit ordinal and ω1CK\omega_{1}^{CK}, the Church-Kleene ordinal, is defined as the set of all recursive ordinals and thus a limit ordinal and the smallest non-recursive ordinal [Church and Kleene (1937), Church (1938), Kleene (1938)]. Another confusing aspect of coinductive logic programming is its “coinductive hypothesis rule of the form ν(n)\nu(n)[Simon et al. (2006), p. 336]101010The coinductive hypothesis rule and ν(n)\nu(n) do not seem to be defined in [Simon et al. (2006)]. which is defined as follows in [Simon et al. (2007), p. 472]: “The operational semantics is given in terms of the coinductive hypothesis rule which states that during execution, if the current resolvent RR contains a call CC^{\prime} that unifies with a call CC encountered earlier, then the call CC^{\prime} succeeds.” The articles [Simon et al. (2006), Simon et al. (2007)] do not explain how that coinductive hypothesis rule relates to the coinduction proof principle. The following examples cast a shadow over the coinductive hypothesis rule:

Example 2.4

   :- coinductive p/2.
   p(X, a) :- p(X, Z).
   p(X, b) :- p(s(X), b).

   ?- p(Y, a).
Example 2.5

   :- coinductive qc/2.
   qc(X, f(X)).

   ?- qc(f(Y), Y).
Example 2.6

   :- inductive q/2.
   qi(X, f(X)), r(X).

   ?- qi(f(Y), Y).
Example 2.7

   :- inductive pi/1.
   pi(_).
   :- coinductive pc/1.
   pc(_).

   ?- X = f(X), pi(X).
   ?- Y = f(Y), pc(Y).
   ?- Z = f(Z), pi(Z), pc(Z).

In Example 2.4, the SLD derivation from the goal ?- p(Y, a). is stopped at the subgoal ?- p(Y, Z). by the coinductive hypothesis rule what prevents the derivation of the subgoal p(s(Y), b) and therefore prevents that the rational term Y = s(Y) (which expresses s(ω)\texttt{s}(\omega)) be returned as answer. Example 2.4 suggests that the coinductive hypothesis rule of coinductive logic programming should not be based on ancestor unification (without occurs-check) but instead on ancestor subsumption (without occurs-check) [Socher-Ambrosius (1992)].

In Example 2.5, since the predicate qc is declared coinductive, the goal ?- qc(f(Y), Y). is unified (without occurs-check) with the fact qc(X, f(X)). yielding as an answer the rational term Y = f(Y) even though no clauses in the program specify non-terminating SLD derivations.

Example 2.6 is like Example 2.5 except that the predicate, now called qi instead of qc, is declared inductive instead of coinductive. Since qc is declared inductive, a unification with occurs-check of ?- qi(f(Y), Y). with qi(X, f(X)). is attempted which fails because of the occurs-check. The articles [Simon et al. (2006), Simon et al. (2007)] give no clues about the intentions behind treating differently cases like Examples 2.5 and 2.6.

In Example 2.7, the goal ?- X = f(X), pi(X). probably fails because pi is declared inductive. Indeed, to the best of the author’s understanding, that implies that unifications involving the variable X perform the occurs-check. In contrast, the goal ?-Y=f(Y),pc(X). probably succeeds returning the answer Y = f(Y) because pi is declared inductive what, as the author understands, means that unifications involving Y do not perform the occurs-check. Note that, according to the examples of [Simon et al. (2007), Section 2.5], in coinductive logic programming the system predicate = is both inductive and coinductive. The three goals of Example 2.7 are therefore licit. Example 2.7 suggests that whether a unification involving a term tt performs the occurs-check or not should depend on the type of tt, data or codata, not on a type inductive or coinductive of predicates in which tt occurs. Example 2.7 raises the question whether with coinductive logic programming as defined in [Simon et al. (2006), Simon et al. (2007)] a same term tt might occur as an argument of both inductive or coinductive predicates, in which case the third goal ?- Z = f(Z), pi(Z), pc(Z). is licit but does not seem to be covered by the semantics given in [Simon et al. (2006), Simon et al. (2007)], or whether inductive and coinductive predicates (except =) cannot share arguments, in which case coinductive logic programming as defined in [Simon et al. (2006), Simon et al. (2007)] would be a rather limited approach.

Coinductive definitions have entered functional programming with lazy evaluation [Henderson and Morris (1976), Friedman and Wise (1976)]. The infinite list of Fibonacci numbers can for example be coded in Haskell as (f 0 1) and the finite list of its 43 first elements as take 43 (f 0 1) where the function f is coded as f a b = a : f b (a+b). A type system for coinductively defined data objects, or codata, has been proposed in [Jeannin et al. (2017)]. The use of the coinduction proof principle for the analysis of functional programs with codata is discussed in [Gordon (1994)]. The lazy evaluation of infinite objects has entered logic programming through logic-functional languages [Giovannetti et al. (1991), Hanus (1994)].

Coinductive definitions have been elegantly formalized in 2005 by Jan Rutten as behavioural differential equations [Rutten (2005)]. Rutten’s behavioural differential equations are further used in [Kupke et al. (2011), Hansen et al. (2017)]. In their term-based form, behavioural differential equations are close to, and extend, the aforementioned representation of rational trees in Prolog II. In the following, coinductive definitions are given in the term-based form of Rutten’s behavioural differential equations.

The coinduction proof principle relates to mathematical induction111111Mathematical induction goes back to the Greek mathematics of the antiquity. because it relates to structural induction which itself derives from mathematical induction. Structural induction has been formalized in 1959 East of the Iron Curtain by Rózsa Péter in [Péter (1961)] and in 1969 West of it by Rod M. Burstall [Burstall (1969)].121212The idea was, however, already “in the air”: Gödel’s article [Gödel (1931)] on the incompleteness theorems bearing his name among others sketches a proof by mathematical induction on degrees of primitive recursive functions which resembles a proof by structural induction.

Proof by (mathematical or structural) induction cannot be completely automated because finding a suitable induction hypothesis is neither decidable, nor semi-decidable: “In contrast to first-order inference, inductive inference is incomplete in the sense that any axiomatization which includes a non-trivial form of induction, there are formulas both true and unprovable” [Bundy (2006)] which follows from Kurt Gödel’s first incompleteness theorem [Gödel (1931)]. Proofs by induction have nonetheless be (incompletely) automated [Boyer and Moore (1988), Bundy (2006), Comon (2006), Avenhaus et al. (2003)] in two manners: Explicitly [Bundy (2006)] and implicitly after the approach called “inductive completion” or “inductionless induction” [Comon (2006)]. The later approach consists in assuming the conjecture to prove, in attempting to derive an inconsistency using the Knuth-Bendix completion algorithm [Knuth and Bendix (1967)], and if no inconsistency is derived to consider the conjecture proved. Observe that inductive completion (or inductionless induction) resembles the coinduction proof principle.131313This resemblance seems to have so far remained unnoticed.

Proofs by induction are supported by proof assistants [Geuvers (2009)], that is, proof systems requiring the participation of their human users. Coinduction as a proof method is usually described as dual of induction, a description referring to the coalgebras of category theory [Jacobs and Rutten (1997)]. Like proofs by induction and for the same reason, proofs by coinduction cannot be completely automated. Coinduction as a proof method has been formalized in higher-order logic and automated with the proof assistant Isabelle as reported in [Paulson (1997)] and in terms of Labelled Transition Systems (LTSs) in [Pous and Sangiorgi (2011)]. Like proofs by induction, proofs by coinduction have been partly automated in proof assistants [Paulson (1997)].

A proof method which resembles the coinduction proof principle has been proposed for logic programming in 2008 by Joxan Jaffar, Andrew Santosa and Răzvan Voicu in [Jaffar et al. (2008)]. The authors stress in this article that the proof method they propose refers to the least fixpoint semantics, not to the greatest fixpoint semantics of of logic programs: “we would like to clarify that the use of the term coinduction pertains to the way the proof rules are employed for a proof obligation GHG\models H, and has no bearing on the greatest fixed point of the underlying logic program P. In fact, our proof method, when applied successfully, proves that GG is a subset of HH wrt. the least fixpoint of (the operator associated with) the program” [Jaffar et al. (2008)]. In contrast to standard induction and coinduction proof methods, the proof method proposed in [Jaffar et al. (2008)] can be completely automated: “a search-based method […] automatically discovers the opportunity of applying induction instead of the user having to specify some induction schema”, “our method is amenable to automation” and “the unfolding process and the application of the coinduction principle require no manual intervention” [Jaffar et al. (2008)]. The generalized coinduction proof principle (see Section 7 below) precises how the proof method of [Jaffar et al. (2008)] relate to the coinduction proof principle.

Jan Rutten gives in [Jacobs and Rutten (1997), Rutten (2000), Rutten (2005)] coalgebraic treatments of coinduction.

Davide Sangiorgi’s book [Sangiorgi (2012)] is a comprehensive introduction to coinduction, bisimulation and the coinduction proof principle which, however, does not address coinduction in declarative programming and does not mention inductionless induction [Comon (2006)].

3 Coinductive Definitions

This section introduces terms of type codata, short codata terms after one of the formalisms which have been proposed for the finite representation of constructed streams [Rutten (2005), Kupke et al. (2011)]. Codata terms rely on corecursive definitions which are introduced in the next section.

Two disjoint data types are considered in the following: Data for the representation of non-stream objects and codata for the representation of streams the elements of which are of type data. Considering only the two types data and codata is a convenient simplification. In practice, the type data consists of several pairwise disjoint types like integer, floating-point number, character, etc. and structured types like finite list of integers, finite list of floating-point numbers, finite list of characters, etc. Streams of streams could be considered, though, since such streams might make sense for example in specifying stream processing operations but such streams and the issues they raise are not addressed in this article.

The type codata encompasses codata terms and their names. The following illustrates on the Fibonacci function the concept of codata term and of name, base cases and defining expression of a codata term:

fib as [0, 1 | fib^0 + fib^1]

This expression is a codata term. Its name is fib, its base cases are 0 and 1 and its defining expression is fib^0 + fib^1. In contrast to [Rutten (2005)], the keyword as is used instead of = for avoiding a confusion with the the Prolog fashion’s use of = in the former section of this article for denoting unification. Codata terms as illustrated above and defined below slightly generalise those of [Rutten (2005)] by allowing compound codata names which are needed for expressing mutual corecursion.

It is convenient to think of the codata term fib as a definition of an infinite list, a view which is justified below in Section 5. fib^0 denotes fib and for all natural number n, fib^(n+1) denotes the tail of fib^(n). Thus, fib^1 denotes the tail of fib.

If f and g respectively represent

[f(0), f(1), ..., f(n), ...]
[g(0), g(1), ..., g(n), ...]

then f+g represents

[f(0)+g(0), f(1)+g(1), ..., f(n)+g(n), ...]

(see below Section 5). Thus, the definition

fib as [0, 1 | fib^0 + fib^1]

can be step-wise expanded yielding

[0, 1 | fib^0 + fib^1]
[0, 1, 1 | fib^1 + fib^2]
[0, 1, 1, 2 | fib^2 + fib^3]
[0, 1, 1, 2, 3 | fib^3 + fib^4]
[0, 1, 1, 2, 3, 5 | fib^4 + fib^5]
etc.

Even though the codata term fib is a recursive definition of the Fibonacci function, it specifies an iterative computation, as does a tail recursive definition [Friedman and Wise (1974), Steele (1977)], but it does not require accumulators, in contrast to a tail recursive definition. This is an essential aspect of coinductive definitions which can be expressed in logic programming parlance as follows: Codata are meant to express forward chaining inferences as defined by the immediate consequence operator TT [van Emden and Kowalsi (1976)].

In the following, Data denotes the set of terms of type data and Codata denotes the set of terms of type codata. In Section 5 below, it is shown that a codata term s as [s0, s1, ..., sn | E] with s a constant induces the definition of a function:

s: \mathbb{N}\rightarrow Data

This justifies to view s as a definition of the infinite list

[s(0), s(1), s(2),..., s(n), ...]

and the following definitions.

Definition 3.1 (Codata names)

A codata name is either a codata constant (called an atomic codata name), or a tuple of codata constants (called a compound codata name).

If (s1,sm)(\texttt{s}_{1},\ldots\texttt{s}_{m}) with m2m\geq 2 is a compound codata name and if n{0}n\in\mathbb{N}\setminus\{0\}, then (s1,sm)(n)(\texttt{s}_{1},\ldots\texttt{s}_{m})(n) denotes (s1(n),sm(n))(\texttt{s}_{1}(n),\ldots\texttt{s}_{m}(n)).

Definition 3.2 (Head, tail, nn-tail, nnth element of a codata term)

Let s be a codata name.

  • s(n) denotes the nnth element of s.

  • s(0) is the head of s.

  • s^0 = s

  • s^1 is the tail of s which expresses the infinite list
    [s(1), s(2),..., s(n), ...]

  • for all nn\in\mathbb{N} s^(n+1) = s^n^1

  • for all nn\in\mathbb{N} s^n is the nnth-tail of s

It follows from Definition 3.2 by mathematical induction that for all nn\in\mathbb{N} and mm\in\mathbb{N} s^n^m = s^(n+m).

Definition 3.3 (Codata term)

A codata term or codata definition is an expression of the form s as [s0, s1, ..., sn | E] where:

  • s is an atomic or compound codata name.

  • n0n\geq 0.

  • the si, 0in0\leq i\leq n, are terms of sort data called the base cases.

  • E is a codata expression.

s as [s0, s1, ..., sn | E] is a definition of s and s is called the name of the codata term.

Codata expressions are defined below in Section 4.

Example 3.1

The following mutually recursive functions

f(0)f(0) == 0
g(0)g(0) == 11
f(n)f(n) == g(n1)g(n-1) for n1n\geq 1
g(n)g(n) == 2×f(n1)2\times f(n-1) for n1n\geq 1

can be expressed by the following codata term:

(f, g) as [(0, 1) | (g, 2*f)]

Defining expressions like 2*f are defined below in Section 4.

Definition 3.4 (Well-formed codata term)

A codata term

s as [s0, s1, ..., sn | E]

is well-formed if

  1. 1.

    For all i=1,,ni=1,\ldots,n, si and s are either both atomic or tuples of the same size.

  2. 2.

    If s is atomic, then E defines an atomic codata, else E defines a tuple of the size of s.

  3. 3.

    All atomic names occurring in the defining expression E also occur in the codata name s.

  4. 4.

    If the defining expression E refers to a kkth tail t^k, then nk+1n\geq k+1.

The first two conditions ensure that the name, the base cases and the defining expression of a codata term are consistent in their sizes. The third conditions ensures that every name referred to in a codata term is defined in that codata term. The fourth and last condition ensures that the number of base cases in a codata term and the references to tails in that codata term’s defining expression are consistent.

Example 3.2

Using nat, a codata term expressing the sequence of natural numbers, Douglas Hofstadter’s female and male sequences [Hofstadter (1979)]:

f(0)f(0) == 11
m(0)m(0) == 0
f(n)f(n) == nm(f(n1))n-m(f(n-1)) for n1n\geq 1
m(n)m(n) == nf(m(n1))n-f(m(n-1)) for n1n\geq 1

can be expressed by the following codata term:

(nat,f,m) as [(0,1,0) | (1+nat,nat-m^f,nat-f^m)]

This example shows that codata terms can express non-linear recurrence relations. Such a definition requires a more involved notion of well-formedness than that given above in Definition 3.4, though. This more involved notion of well-formedness is out of the scope of this article.

4 Corecursive Definitions

The qualifier “inductive” (“coinductive”, respectively) refers to data (codata, respectively) definitions while the qualifier “recursive” (“corecursive”, respectively) refers to the definitions of functions or predicates on data (codata, respectively). In most cases, the pedantic distinction (co)inductive/(co)recursive can be ignored. Furthermore, this distinction is blurred in the presence of codata which can be seen both as infinite lists and function definitions. The distinction is nonetheless used in the titles of this section and of the former section because it provides a convenient structuring of the exposition.

In the following, pointwise means element-wise and refers to the interpretation of codata terms as infinite lists which is justified below in Section 5. In the following, all corecursive definitions refer to natural numbers. Example of corecursive referring to other data types (like Boolean, characters, strings of characters, etc.) can easily be derived from the following “number-based” examples.

If ad is a data constant, then the codata constant ac is defined by:
ac as [ad | ac]

The sum of a data constant ad and a codata s is defined by:
ad+s as [ad + s(0) | ad + s^1]

The pointwise product of codata s and t is defined by:
s*t as [s(0) * t(0) | s^1 * t^1]

The codata nat (natural numbers) is defined by:
nat as [0 | 1d + nat].

The pointwise sum s+t of codata s and t is defined by:
s+t as [s(0) + t(0) | s^1 + t^1]

The codata nat (natural numbers) can also be defined by:
nat as [0 | 1c + nat]

The product of a data constant ad and a codata s is defined by:
ad*s as [ad * s(0) | ad * s^1]

The pointwise pairing of codata s and t is defined by:
(s, t) as [(s(0), t(0)) | (s^1, t^1)]

The pointwise application of data term constructor ff to codata s is defined by:
f(s) as [f(s(0)) | f(s^1)]

Right-side sums and products with data constants are defined similarly to the left-side sums and products with data constants specified above. Pointwise nn-groupings for n3n\geq 3 of codata are defined similarly to the pairing of codata.

Further examples of corecursive definitions [Rutten (2005)], where s and t are codata names:

even(s) as [s(0) | even(s^2)]
odd(s) as [s^1(0) | odd(s^2)]
split(s) as (even(s), odd(s))
zip(s, t) as [s(0) | zip(t, s^1)]

The codata fact (factorial numbers) is defined by:

fact as [1 | nat^1 * fact]
Definition 4.1 (Codata expression)

A codata expression is a codata nn-th tail (including a codata name) or the application of a corecursive function to codata expression(s).

Let s as [s0, s1, ..., sn | E] be a codata term with an atomic name. s immediately depends on every codata constant and every codata name occurring in the codata expression E. Depends is used for the transitive closure of directly depends.

Immediate dependency extends component-wise to compound codata names.

Definition 4.2 (Structural codata expression)

A codata expression is structural if it contains neither sums, nor products.

More generally, a function definition is structural if its does not involve expressions determining values of which requires reductions (that is, computations).

Observe that the corecursive function definitions given above are all pointwise. Observe also that the codata constants, the codata pairing and grouping and the pointwise data term application are the only structural cases of structural corecursion given above.

5 Interpretation of Codata as Infinite Streams

This section shows that a codata term s as [s0, s1, ..., sn | E] specifies an infinite list in the sense that it induces the definition of a function s: m\mathbb{N}^{m}\rightarrow Data where mm is the dimension of s, that is, m=1m=1 if s is atomic, and mm is the tuple size of s otherwise. The overloading of the symbol s used both as a codata name and a function name is intentional and justified by Definition 3.2 of Section 3.

Definition 5.1

Let s as [d1, ... , dk | E] be a codata term.

The notation E[s0, ..., sn] expresses that the set of atomic codata names occurring in expression E is {\{s,0,{}_{0},\ldots, s}n{}_{n}\}, that is, for all 0in0\leq i\leq n, si == s(i).

E^0 denotes E and if k{0}k\in\mathbb{N}\setminus\{0\}, then E^k denotes the expression obtained from expression E by replacing every nnth-tail t^n in E by t^n^k.

Thus, by Definition 5.1, if kk\in\mathbb{N}, then

E[s0, ..., si, ..., sn]^k

denotes

E[s0^k, ..., si^k, ..., sn^k].

Definition 5.2 (nnth expansion of a codata term)

Let

s as [s0, s1, ..., sk | E]

be a codata term and let nkn\geq k be a natural number. The nnth expansion of s is the codata term

s[n] as [s(0), ..., s(k), ..., s(n) | E^(n-k)]

obtained from s by repeatedly applying the codata term defining expression E. Recall that for all 0ik0\leq i\leq k, si == s(i).

Section 3 above gives examples of expansions of the codata term fib. The following shows that the applications mentioned in Definition 5.2 terminate if the codata term considered is well-formed.

Proposition 5.1 (Expansion Theorem)

For all well-formed codata terms s as [s0, s1, ..., sk | E] and all nn\in\mathbb{N} such that nkn\geq k, the nnth expansion s[n] of s is uniquely defined.

Proof 5.1.

First observe that if s as [s0, s1, ..., sk | E] is a well-formed codata term, then s (directly or indirectly) depends on finitely many codata names all occurring in s. Second, observe that [s0, s1, ..., sk | E] is its kkth expansion of s. The result follows by structural induction.

Definition 5.2 (nnth element of a codata term).

Let

s as [s0, s1, ..., sn | E]

be a well-formed codata term and let m{0}m\in\mathbb{N}\setminus\{0\} be the dimension of s. The codata term s induces a function

s: m\mathbb{N}^{m}\rightarrow Data

defined by: for nn\in\mathbb{N} s(n) is the head of the nnth expansion of s.

By the Expansion Theorem, the function s: m\mathbb{N}^{m}\rightarrow Data referred to in Definition 5.2 is well-defined. As a consequence, a well-formed codata term s can be viewed as a definition of the infinite list

[s(0), s(1), s(2),..., s(n), ...]

and the concepts of Definition 3.2 from Section 3 above are well-defined.

Corollary 5.3 (tail computation).

Let s=(s0,s1,,sk)\texttt{s}=(\texttt{s}_{0},\texttt{s}_{1},\ldots,\texttt{s}_{k}) with k1k\geq 1 be the name of a well-formed codata term.

  1. 1.

    For all nn\in\mathbb{N} and ms^n^m=m\in\mathbb{N}~{}s{{\hat{\hskip 5.0pt}}}n{{\hat{\hskip 5.0pt}}}m= s^(n+m)={{\hat{\hskip 5.0pt}}}(n+m)= s^n(m)={{\hat{\hskip 5.0pt}}}n(m)= s^m(n){{\hat{\hskip 5.0pt}}}m(n)

  2. 2.

    If s as [d1, ..., dk | E[s0, ..., sk)]], then for all nn\in\mathbb{N}, if nkn\geq k then
    s^n = E[s0^(n-k), ..., sk^(n-k)].

Proof 5.4.

By structural induction and the Expansion Theorem 5.1.

A few remarks are worthwhile.

First, even though the set of infinite lists on a finite alphabet is not enumerable,141414This can be proven by the diagonalisation argument Georg Cantor used for proving that the set of decimal numbers is not countable [Cantor (1891)]. the set of codata terms on a finite alphabet is recursively enumerable. Indeed, like a data term, codata terms are finite expression which can be inductively defined. Thus, using the terminology of the introduction, not all observed streams can be specified as constructed streams.

Second, two distinct codata terms might specify the same infinite stream as is the case for example with s1 = [1 | s1] and s2 = [1, 1 | s2] which both specify the same codata constant specifying the infinite list of 1s1s: [1, 1, 1, ...].

Third, let s and t be the names of two well-formed codata terms. Whether for all nn\in\mathbb{N} s(n) = t(n) (that is, s and t specify the same infinite list) is neither decidable nor semi-decidable. Algorithms are possible, though, which in some cases will decide whether, or recognize that, two codata terms specify a same infinite list or whether all elements of the infinite list specified by a codata term has a certain property.

Fourth and finally, it is worth stressing that one of the interests of codata terms is to (corecursively) define functions f:f:\mathbb{N}\rightarrow Data without having to give an equation on nn for f(n)f(n). There are indeed cases in which this is desirable. The Fibonacci function for example has a simple recursive definition, fib as [0, 1 | fib + fib^1], but a significantly more complicated definition as an equation on nn:

fib(n)=[(1+5)n2n5]\textrm{fib}(n)=\left[\frac{(1+\sqrt{5})^{n}}{2^{n}\sqrt{5}}\right]

In other cases, however, an equation on nn is simpler than a recursive definition: For all nf(n)=nn\in\mathbb{N}~{}f(n)=n is for example simpler than:

nat as [0 | 1 + nat]

6 First Generalized Coinduction Theorem

In this section and the following, a predicate is called a data predicate if all its arguments are of type data and a predicate is called a codata predicate if all its arguments are of type codata, data predicates are denoted by identifiers beginning with lower case characters and codata predicates are denoted by identifiers beginning with upper case characters, codata terms are implicitly assumed to be well-formed and the phrase “the codata term s” refers to a (well-formed) codata term of the form s as [d1, ... , dk | E] with k1k\geq 1.

Definition 6.1 (Pointwise-defined and hereditary codata predicate).

Let pp be a unary data predicate and ss a codata name.

The unary codata predicate PpP_{p} defined by:

For all codata term ss, Pp(s)P_{p}(s) iff for all np(s(n))n\in\mathbb{N}~{}p(s(n))

is called the pointwise-derived from pp.

A unary codata predicate HH which fulfills the following condition is said to be hereditary with respect to pp, short pp-hereditary:
If H(s)H(s) holds of some codata ss, then

  1. 1.

    p(s(0))p(s(0)) holds.

  2. 2.

    H(s^1)H(s{{\hat{\hskip 5.0pt}}}1) holds.

Lemma 6.2.

Let pp be a unary data predicate. The pointwise-derived PpP_{p} from pp is pp-hereditary.

Proof 6.3.

Let pp be a unary data predicate and let ss be a codata name. By definition of the pointwise-derived PpP_{p} from pp, Pp(s)P_{p}(s) iff for all np(s(n))n\in\mathbb{N}~{}p(s(n)). Thus, if Pp(s)P_{p}(s) holds, then p(s(0))p(s(0)) holds and Pp(s^1)P_{p}(s{{\hat{\hskip 5.0pt}}}1) holds.

Observe that the concept of pp-hereditary codata predicate generalises that of bisimulation relation [Park (1981), Rutten (2005), Sangiorgi (2012)] since a bisimulation relation BB is defined as a binary relation such that s1Bs2s_{1}~{}B~{}s_{2} if

  1. 1.

    s1(0)=s2(0)s_{1}(0)=s_{2}(0)

  2. 2.

    s1^1Bs2^1s_{1}{{\hat{\hskip 5.0pt}}}1~{}B~{}s_{2}{{\hat{\hskip 5.0pt}}}1

More precisely, a bisimulation relation BB is an =-hereditary predicate applying of pair codata (s1,s2)(s_{1},s_{2}). Thanks to codata pairing defined above in Section 4, a binary codata predicate can be seen as a unary codata predicate the argument of which is a pair of codata.

Observe also that if pp is a unary data predicate and P1P_{1} and P2P_{2} are pp-hereditary codata predicates, then the codata predicates AA and OO defined as follows are also pp-hereditary:

For all codata names ss:

  • A(s)A(s) iff (P1(s)P2(s))(P_{1}(s)\land P_{2}(s))

  • O(s)O(s) iff (P1(s)P2(s))(P_{1}(s)\lor P_{2}(s))

Definition 6.4 (Maximal pp-hereditary codata predicate).

Let pp be a unary data predicate. The maximal p-hereditary codata predicate Maxp\textrm{Max}_{p} is defined by:

If HH is a pp-hereditary codata predicate and s is as codata name such that H(s)H(s) holds, then Maxp(s)\textrm{Max}_{p}(s) holds.

Observe that Maxp\textrm{Max}_{p} is the greatest pp-hereditary predicate in the sense that it expresses the union of all unary relations on codata which are defined by unary pp-hereditary codata predicates. Observe also that Maxp\textrm{Max}_{p} generalizes the bisimilarity relation [Park (1981), Rutten (2005), Sangiorgi (2012)] which, in the terminology of Definition 6.4, is Max=\textrm{Max}_{=}.

Theorem 6.5 (First Generalized Coinduction Theorem).

Let ss be the name of a codata term and let pp a unary data predicate. The following statements are equivalent:

  1. 1.

    There is a unary pp-hereditary codata predicate HH such that H(s)H(s) holds.

  2. 2.

    There is a unary pp-hereditary codata predicate HH such that: nH(s^n)\forall n\in\mathbb{N}~{}H(s{{\hat{\hskip 5.0pt}}}n)

  3. 3.

    np(s(n))\forall n\in\mathbb{N}~{}p(s(n))

Proof 6.6.

Let ss be a codata term, pp a unary data predicate and HH a unary codata predicate.

(1) \Rightarrow (2): Assume HH is pp-hereditary and H(s)H(s) holds. The proof is by induction. Since by hypothesis H is pp-hereditary and H(s)H(s) holds, H(s^1)H(s{{\hat{\hskip 5.0pt}}}1) holds. Let nn\in\mathbb{N} and assume that H(s^n)H(s{{\hat{\hskip 5.0pt}}}n) holds. Since by hypothesis H is pp-hereditary and H(s^n)H(s{{\hat{\hskip 5.0pt}}}n) holds, H(s^(n+1))H(s{{\hat{\hskip 5.0pt}}}(n+1)) holds.

(2) \Rightarrow (3): Since by assumption for all nH(s^n)n\in\mathbb{N}~{}H(s{{\hat{\hskip 5.0pt}}}n) holds and HH is pp-hereditary, for all np(s^n(0))=p(s(n))n\in\mathbb{N}~{}p(s{{\hat{\hskip 5.0pt}}}n(0))=p(s(n)) holds.

(3) \Rightarrow (1): If for all np(s(n))n\in\mathbb{N}~{}p(s(n)), then Pp(s)P_{p}(s) holds where PpP_{p} is the pointwise-derived from pp defined in Definition 6.1. By Lemma 6.2, PpP_{p} is pp-hereditary.

7 Generalized Coinduction Proof Principle

Recall that all codata terms considered are implicitly assumed to be well-formed.

Corollary 7.1 (Generalized Coinduction Proof Principle).

Let pp be a unary data predicate and let ss be the name of a codata term. For proving np(s(n))~{}\forall n\in\mathbb{N}~{}p(s(n))~{}

  1. 1.

    it suffices to exhibit a unary codata predicate HH such that:

    1. (a)

      H(s)H(s) holds.

    2. (b)

      HH is pp-hereditary.
      (That is, for all codata names tt, p(t(0))p(t(0)) and H(t^1)H(t{{\hat{\hskip 5.0pt}}}1) holds.)

  2. 2.

    it suffices to exhibit a unary pp-hereditary codata predicate HH such that nH(s^n)\forall n\in\mathbb{N}~{}H(s{{\hat{\hskip 5.0pt}}}n).

Proof 7.2.

(1) is (1) \Rightarrow (3) of Theorem 6.5 and (2) is (2) \Rightarrow (3) of Theorem 6.5.

The generalized coinduction proof principle extends to every unary data predicate the coinduction proof principle formulated in [Park (1981), Rutten (2005), Sangiorgi (2012)] for equality.

If several codata terms mutually depend on each other (in the sense of Definition 4.1, that is, are mutually corecursive), then a proof by strong coinduction referring to one of these codata names ss must, of course, also refer to the codata names ss depends on. This stresses the necessity for the codata terms considered to be well-formed.

For a better understanding, the following examples of proofs by (generalized) coinduction are detailed (and possibly over-detailed).

Example 7.3.

1c as [1 | 1c]

The singleton set consisting of this codata term is well-defined. Let PP be the codata predicate defined by: For all codata name ss, P(s)P(s) if s(0)>0s(0)>0 and s^1=ss{{\hat{\hskip 5.0pt}}}1=s. Thus, PP is (>0)(>0)-hereditary and P(1c)P(\texttt{1}_{c}) holds. By the generalized coinduction proof principle, n\forall n\in\mathbb{N}~{} 1(n)c>0{}_{c}(n)>0.

Example 7.4.

fib = [0, 1 | fib + fib^1]

The singleton set consisting of this co-data term is well-defined. Proof by generalized coinduction of n(n>0\forall n\in\mathbb{N}~{}(n>0\Rightarrow fib(n)>0)(n)>0).

Let PP be the codata predicate defined by: For all codata names ss, P(s)P(s) holds if s(0)>0s(0)>0 and n((s(n)>0s(n+1)>0)s(n+2)>0)\forall n\in\mathbb{N}~{}((s(n)>0\land s(n+1)>0)\Rightarrow s(n+2)>0).

First, PP is shown to be (>0)(>0)-hereditary. Let ss be a codata name. If P(s)P(s) holds, then by definition of PP, s(0)>0s(0)>0 and n((s(n)>0s(n+1)>0)s(n+2)>0)\forall n\in\mathbb{N}~{}((s(n)>0\land s(n+1)>0)\Rightarrow s(n+2)>0). As a consequence, s(1)>0s(1)>0 and n{0}((s(n)>0s(n+1)>0)s(n+2)>0)\forall n\in\mathbb{N}\setminus\{0\}~{}((s(n)>0\land s(n+1)>0)\Rightarrow s(n+2)>0), that is, P(s^1)P(s{{\hat{\hskip 5.0pt}}}1) holds.

Second, it is proved that P(P(fib^1)) holds. fib^1(0)=(0)= fib(1)=1>0(1)=1>0 and fib^1(1)(1) = fib(2)=2>0(2)=2>0. Let nn\in\mathbb{N}. From

fib = [0, 1 | fib + fib^1]

it follows by Corollary 5.3 that

fib^1^2 = fib^1 + fib^1^1

Thus, for all n \in\mathbb{N}:

fib^1(n+2) = fib^2(n+1) =
fib(n+1) + fib^1(n+1) =
fib^1(n) + fib^1(n+1)

It follows that if fib^1(n) >0>0 and fib^1(n+1) >0>0, then
fib^1(n+2) >0>0. Thus P(P(fib^1){{\hat{\hskip 5.0pt}}}1) holds.

The result follows by the generalized coinduction principle.

Example 7.5.

This example is adapted from [Rutten (2005)].

even(s) as [s(0)|even(s^2)]
odd(s) as [s^1(0)|odd(s^2)]
zip(s, t) as [s(0)|zip(t, s^1)]

This set of codata terms is well-defined. Proof by coinduction for all codata name s and t
even(zip(s, t)) = s.

Let PP be the binary codata defined by:
()(\star) for all codata names s and t, PP(even(zip(s, t)), s).

PP is =-hereditary, that is, if P(u,v)P(u,v) holds, then

  1. 1.

    u(0)=v(0)u(0)=v(0)

  2. 2.

    P(u^1,v^1)P(u{{\hat{\hskip 5.0pt}}}1,v{{\hat{\hskip 5.0pt}}}1)

(1) follows from the fact that ()(\star) implies even(zip(s, t))(0) = s(0) what is proven as follows:

even(zip(s, t))(0) = (by def.  of even)
zip(s, t)(0) = (by def. of zip)
s(0)

(2) follows from the fact that ()(\star) implies that for all codata names s and t
PP(even(zip(s, t))^1, s^1) holds, as it is now shown. Let s and t be codata names.

even(zip(s, t))^1 =
even(zip(s, t)^2) =
even(zip(s, t)^1) =
even(zip(t, s^1)^1) =
even(zip(s^1, t^1))

Thus, PP(even(zip(s, t))^1, s^1) holds iff:

PP(even(zip(s^1, t^1), s^1)

holds. By ()(\star),

PP(even(zip(s^1, t^1), s^1)

holds, that is,

PP(even(zip(s, t))^1, s^1)

holds. By the coinduction proof principle, it follows that:

even(zip(s, t)) = s.

The proof by coinduction of zip(even(s), odd(s)) = s of Example 7.5 given above stresses an aspect of some proofs by coinduction. A codata predicate PP is constructed as the closure over tails of codata, what is often described as the computation of a greatest fixpoint [Rutten (2005), Sangiorgi (2012)]. This view is recalled in the following.

Let pp be a unary data predicate and consider the following operator Φp\Phi_{p} on the unary codata relations:

Φp\Phi_{p}: 𝒫(Codata)\mathcal{P}(\mathrm{Codata}) \rightarrow 𝒫(Codata)\mathcal{P}(\mathrm{Codata})
RR \rightarrow {sCodatap(s(0))R(s^1)}\{s\in\mathrm{Codata}\mid p(s(0))\land R(s{{\hat{\hskip 5.0pt}}}1)\}

If ss is a codata name, a proof by generalized coinduction of

np(n)\forall n\in\mathbb{N}~{}p(n)

consists in establishing the existence of a unary pp-hereditary predicate RR, which defines a unary relation on 𝒫(Codata)\mathcal{P}(\mathrm{Codata}), such that R(s)R(s) holds, that is, that RΦp(R)R\subseteq\Phi_{p}(R) that means that RR is a post-fixpoint of Φp\Phi_{p}. By a theorem of Knaster [Knaster (1928), Tarski (1930), Tarski (1955)] commonly called the Knaster-Tarski theorem, the greatest fixpoint of Φp\Phi_{p} is the unary relation on Codata characterized by the predicate Maxp\textrm{Max}_{p} defined above in Definition 6.4.151515The greatest fixpoint Maxp\textrm{Max}_{p} of Φp\Phi_{p} is unrelated to the greatest fixpoint semantics of logic programs [Abdallah (1983), Abdallah (1984), van Emden and Abdallah (1985), Lloyd (1987)] mentioned in Section 2.

The need for a strengthening of the definition of the predicate to be proven pp-hereditary in a proof by coinduction, as in the proof given in Example 7.5 above, is not specific of coinduction proofs. Such strengthening are common in induction proofs where they are called “induction loading”. A traditional example of induction loading is that a proof by induction of

n{0}i=1i=n1i2<2\forall n\in\mathbb{N}\setminus\{0\}~{}\sum_{i=1}^{i=n}\frac{1}{i^{2}}<2

which is impossible without strengthening that statement for example into:

n{0}i=1i=n1i221n\forall n\in\mathbb{N}\setminus\{0\}~{}\sum_{i=1}^{i=n}\frac{1}{i^{2}}\leq 2-\frac{1}{n}
Example 7.6.

Proof by coinduction of:

()ni=0i=ni=n×(n+1)2(\dagger)\hskip 10.00002pt\forall n\in\mathbb{N}~{}\sum_{i=0}^{i=n}i=\frac{n\times(n+1)}{2}

Consider the following well-formed codata terms:161616This example assumes that the product of codata with data constants defined above in Section 4 is extended to rational numbers.171717The definitions of sum1 and sum2 differ in a significant aspect: While sum1 is corecursively defined, sum2 is not corecursively defined.

(nat, sum1) as [(0, 0)|(1+nat, 1+nat+sum1)]
(nat, sum2) as [(0, 0)|(1+nat, (1/2)*nat*(1+nat))]

First, a codata predicate PP is defined as follows: For all codata names ss and tt, P(s,t)P(s,t) if

  1. 1.

    s(0)=t(0)s(0)=t(0)

  2. 2.

    n(s(n)=t(n)s(n+1)=t(n+1))\forall n\in\mathbb{N}~{}(s(n)=t(n)\Rightarrow s(n+1)=t(n+1))

Second, it is proved that PP is =-hereditary. Let ss and tt be codata names such that P(s,t)P(s,t) holds. By (1) of the definition of PP, s(0)=t(0)s(0)=t(0). If follows now from (2) of the definition of PP that s(1)=t(1)s(1)=t(1). If also follows from (2) of the definition of PP that n 0(s(n)=t(n)s(n+1)=t(n+1))\forall n\in\mathbb{N}\ {0}~{}(s(n)=t(n)\Rightarrow s(n+1)=t(n+1)). This means that P(s^1,t^1)P(s{{\hat{\hskip 5.0pt}}}1,t{{\hat{\hskip 5.0pt}}}1) what completes the proof that P is =-hereditary.

Third, it is proved that PP(sum1, sum2) holds. By definition of sum1 and sum2, sum1(0)=(0)= sum2(0)(0). Let n \in\mathbb{N} and assume that sum1(n)=(n)= sum2(n)(n). By definition of sum1:

sum1(n+1) = sum1^(n) + (n+1)

By definition of sum2:

sum2(n+1)=(n+1)×(n+2)2=n×(n+1)2+(n+1)=(n+1)=\frac{(n+1)\times(n+2)}{2}=\frac{n\times(n+1)}{2}+(n+1)= sum2(n)+(n+1)(n)+(n+1)

Thus, \forall n (\in\mathbb{N}~{}(sum1(n)=(n)= sum2(n)(n)\Rightarrow sum1(n+1)=(n+1)= sum2(n+1))(n+1)). This completes the proof that PP(sum1, sum2) holds and, by the generalized coinduction proof principle, that of ()(\dagger).

Under certain notational assumption, the proof of n(n>0\forall n\in\mathbb{N}~{}(n>0\Rightarrow fib(n)>0)(n)>0) given in Example 7.4 can be shortened as follows. From

fib = [0, 1 | fib + fib^1]

it follows that

fib^1 as [1, 1 | fib^1 + fib^2]

Thus, if fib^1 >0>0 and fib^2 >0>0, then fib^1 + f^2 >0>0. Since fib^1(0)=(0)= fib^1(1)=1(1)=1, the result holds by the generalized coinduction proof principle

The notational assumption giving sense to the above proof is that if pp denotes a data predicate, then the pointwise-derived from pp, PpP_{p}, defined in 6.1, is also denoted pp, the context allowing to disambiguate. The first sentence above states that the expression defining fib^1, fib^1 + fib^2, preserves the pointwise-derived of (>0)(>0), P(>0)P_{(>0)}. This is indeed the case because so does the “down-lifted” of that expression to the data: If ss and tt are data names such that s>0s>0 and t>0t>0, then s+t>0s+t>0. The second sentence states that each of the finitely many initial values defining fib^1 does satisfy the data predicate (>0)(>0).

Under the same notational assumption, the proof can also be expressed as follows. Assume fib^1 > 0. fib^1(0)=1(0)=1 and fib^2(1)=1(1)=1 and since fib^1 > 0, fib^1 + fib^2 > 0. Since there are no contradictions, the assumption fib^1 > 0 follows by the generalized coinduction proof principle.

It is similar shortened bisimulation proofs that have made the coinduction proof principle ”seem a bit magical” [Kozen and Silva (2016), p. 2].

Example 7.6 suggests the following theorem.

Theorem 7.7 (Second Generalized Coinduction Theorem).

The principle of mathematical induction and the generalized coinduction proof principle follow from each other.

Proof 7.8.

Since the First Generalized Coinduction Theorem 6.5, from which generalized coinduction proof principle is derived, is proved above by induction, it suffices to show that the principle of mathematical induction follows from the generalized coinduction proof principle.

Assume that pp is a unary data predicate such that p(0)p(0) holds and n(p(n)p(n+1))\forall n\in\mathbb{N}~{}(p(n)\Rightarrow p(n+1)). We show that the generalized coinduction proof principle implies that np(n)\forall n\in\mathbb{N}~{}p(n).

Let PP be a codata predicate defined by:

For all codata names ss, P(s)P(s) holds if

  1. 1.

    p(s(0))p(s(0))

  2. 2.

    np(s(n))p(s(n+1))\forall n\in\mathbb{N}~{}p(s(n))\Rightarrow p(s(n+1))

Let ss be a codata name. Assume P(s))P(s)) holds. it follows from the definition of PP that p(s(1))p(s(1)) holds and that n{0}p(s(n))p(s(n+1))\forall n\in\mathbb{N}\setminus\{0\}~{}p(s(n))\Rightarrow p(s(n+1)), that is, by definition of PP, P(s^1)P(s{{\hat{\hskip 5.0pt}}}1) holds. Thus, PP is pp-hereditary. By the generalized coinduction proof principle, np(n)\forall n\in\mathbb{N}~{}p(n), what completes the proof.

8 Perspectives and Conclusion

An observed stream is a possibly never ending sequence of observations or measurements of natural or artificial systems like temperatures, the reproduction rates of a disease, and energy consumption or traffic volumes. Observed streams are compared with behavioral models, typically for detecting situations of interest like critical raises of a stream’s data.

Behavioral models of observed streams can be expressed as constructed, or synthetic, streams specified as codata terms (as defined in Sections 3 and 4). Functions or predicate on codata then give rise to express properties of such models which can be established using the generalized coinduction proof. A proof similar to that of Example 7.3 for example establishes that s1 == s2 if s1 and s2 are defined by:

s1 as [1 | s1]
s2 as [1, 1 | s2]

For a less trivial example, consider the following codata terms which specify repeating oscillations over respectively 2, 3 and 6 states denoted 0 to 5:

o2 as [0, 1 | o2]
o3 as [0, 1, 2 | o3]
o6 as [0, 1, 2, 3, 4, 5 | o6]
Definition 8.1.

The codata s and t as finitely equivalent, denoted s f\sim_{f} t, if for some nn\in\mathbb{N}:

  1. 1.

    there is a bijection

    b:b: {s(0),,s(n)}\{\texttt{s}(0),\ldots,\texttt{s}(n)\} \rightarrow {t(0),,t(n)}\{\texttt{t}(0),\ldots,\texttt{t}(n)\}
    s(i)\texttt{s}(i) \rightarrow t(i)\texttt{t}(i)
  2. 2.

    for all ms(n+m)=s(n)m\in\mathbb{N}~{}\texttt{s}(n+m)=\texttt{s}(n) and t(n+m)=t(n)\texttt{t}(n+m)=\texttt{t}(n)

Recall that (o2,o3) defines (see Section 4) the stream:
[(0,0), (1,1), (0,2), (1,0), (0,1), (1,2), (0,0), ...] A proof similar to that of Example 7.3 establishes that

(o2,o3) f\sim_{f} o6

that is, (o2,o3) specifies a stream endlessly oscillating over 6 states.

Consider now the codata term

n as [0 | s(n)]

which specifies the stream:

[0, s(0), s(s(0)), s(s(s(0))), ...]

Recall the following codata term from Section 4 which specifies the stream of natural numbers:

nat as [0 | 1 + nat]

A proof by generalized coinduction that n f\sim_{f} nat does not essentially differ from the proof given in Example 7.3 and from the above-mentioned proof of (o2,o3) f\sim_{f} o6.

The aforementioned proofs by generalized coinduction have in common that they refer either to structurally defined codata (in the sense of Definition 4.2) or, for the last one, to a decidable first-order theory, Presburger arithmetic [Presburger (1929)]. As a consequence, such proofs can be automated. More precisely, proofs of the finite equivalence (in the sense of f\sim_{f} defined above) of structurally defined codata terms (in the sense of Definition 4.2) and of codata terms defined in terms of decidable theories can be completely automated and therefore supported by a declarative, functional or logic, programming language.181818The technique needed for such an automation is equational unification or e-unification [Plotkin (1972), (72), Degtyarev and Voronkov (1984), Tiwari et al. (2000), Escobar et al. (2009)].

A declarative programming language providing automated proofs by generalized coinduction for codata terms defined in terms of decidable theories would be a useful tool for processing observed streams.

This article has first given an extensive review of coinduction in declarative programming. Second, it has reviewed and slightly extended the codata formalism. Third, it has generalized to any predicate the coinduction proof principle which was originally specified for the equality predicate only. This generalization has been shown to make the coinduction proof principle more intuitive by making better visible its closeness with structural induction. The article has finally suggested to extend declarative, functional or logic, programming with a limited, decidable form of the generalized of the coinduction proof principle based upon structural codata definitions or upon codata definitions referring to decidable theories.

Acknowledgments

The author thanks Schloss Dagstuhl – Leibniz Rechenzentrum für Informatik and Alexander Artikis, Thomas Eiter, Alessandro Margara, and Stijn Vansummeren, the organisers of the Dagstuhl Seminar “Foundations of Composite Event Recognition” (February 9–14, 2020, https://www.dagstuhl.de/20071), for their invitation to present an early version of the work reported about in this article at the seminar.

The author thanks the seminar participants for their useful comments on his seminar presentation.

References

  • Abdallah (1983) Abdallah, N. M. A. 1983. Metric interpretations and greatest fixpoint semantics of logic programs. Research Report CS-83-29, Department of Computer Science, University of Waterloo, Ontario, Canada.
  • Abdallah (1984) Abdallah, N. M. A. 1984. On the interpretation of infinite computations in logic programming. In Proceedings of the 11th International Colloquium on Automata, Languages and Programming (ICALP). LNCS, vol. 172. Springer, 358–370.
  • Ancona (2013) Ancona, D. 2013. Regular corecursion in Prolog. Computer Languages, Systems & Structures 39, 4, 142–162. Special issue on the Programming Languages track at the 27th ACM Symposium on Applied Computing, 2012.
  • Ancona et al. (2017) Ancona, D., Dagnino, F., and Zucca, E. 2017. Extending coinductive logic programming with co-facts. In Proceedings of the First Workshop on Coalgebra, Horn Clause Logic Programming and Types, E. Komendantskaya and J. Power, Eds. 1–18.
  • Avenhaus et al. (2003) Avenhaus, J., Kühler, U., Schmidt-Samoa, T., and Wirth, C.-P. 2003. How to prove inductive theorems? quodlibet! In Automated Deduction – Proceedings of the International Conference on Automated Deduction (CADE), F. Baader, Ed. LNCS, vol. 2741. Springer, 328–333.
  • Boyer and Moore (1988) Boyer, R. S. and Moore, J. S. 1988. Integrating decision procedures into heuristic theorem provers: A case study of linear arithmetic. Machine Intelligence 11, 83–124.
  • Bundy (2006) Bundy, A. 2001, 2006. Handbook of Automated Reasoning. Vol. 1. MIT Press, Chapter The automation of proof by mathematical induction, 845–912.
  • Burstall (1969) Burstall, R. M. 1969. Proving properties of programs by structural induction. The Computer Journal 12, 1, 41–48.
  • Cantor (1891) Cantor, G. 1891. Über eine elementare Frage der Mannigfaltigkeitslehre. Jahresbericht der Deutschen Mathematiker-Vereinigung 1, 75–18.
  • Church (1938) Church, A. 1938. The constructive second number class. Bulletin of the American Mathematical Society 44, 4, 224–232.
  • Church and Kleene (1937) Church, A. and Kleene, S. C. 1937. Formal definitions in the theory of ordinal numbers. Fundamenta Mathematicae 28, 11–21.
  • Clark (1978) Clark, K. L. 1978. Logic and Data Bases. Plenum, New York, USA, Chapter Negation as Failure, 293–324.
  • Colmerauer (1982) Colmerauer, A. 1982. Logic Programming. Academic Press, Cambridge, MA, USA, Chapter Prolog and Infinite Trees, 231–251.
  • Colmerauer (1984) Colmerauer, A. 1984. Equations and inequations on finite and infinite trees. In Proceedings of the International Conference on Fifth Generation Computer Systems (FGCS), I. for New Generation Computer Technology (ICOT), Ed. Ohmsha Ltd. and North-Holland, Tokyo, Japan, and Amsterdam, The Netherland, 85–99.
  • Colmerauer (1988) Colmerauer, A. 1988. Personal communication.
  • Comon (2006) Comon, H. 2001, 2006. Handbook of Automated Reasoning. Vol. 1. MIT Press, Chapter Inductionless Induction, 913–962.
  • Courcelle (1983) Courcelle, B. 1983. Fundamental properties of infinite trees. Theoretical Computer Science 25, 95–169.
  • Degtyarev and Voronkov (1984) Degtyarev, A. and Voronkov, A. 1984. What you always wanted to know about rigid e-unification. Journal of Automated Reasoning 20, 47–80.
  • Escobar et al. (2009) Escobar, S., Meseguer, J., and Sasse, R. 2009. Variant narrowing and equational unification. Electronic Notes in Theoretical Computer Science 238, 3, 103–119.
  • Fitting (2002) Fitting, M. 2002. Fixpoint semantics for logic programming – a survey. Theoretical Computer Science 278, 1-2, 25–51.
  • Fokkink (2007) Fokkink, W. 1999, 2007. Introduction to Process Algebra. Springer.
  • Friedman and Wise (1974) Friedman, D. P. and Wise, D. S. 1974. Unwinding structured recursions into iterations. Technical Report 19, Conmputer Science Department Indiana University, Bloomington, Indiana, USA.
  • Friedman and Wise (1976) Friedman, D. P. and Wise, D. S. 1976. Cons should not evaluate its arguments. In Third International Colloquium on Automata Languages and Programming (ICALP), S. Michaelson and R. Milner, Eds. Edinburgh University Press.
  • Geuvers (2009) Geuvers, H. 2009. Proof assistants: History, ideas and future. Sādhanā 34, 3–25.
  • Giovannetti et al. (1991) Giovannetti, E., Levi, G., Moiso, C., and Palamidessi, C. 1991. Kernel-leaf: A logic plus functional language. Journal of Computer and System Sciences (JCSS) 42, 2, 1349–185.
  • Gödel (1931) Gödel, K. 1931. Über formal unentscheidbare Sätze der “Principia Mathematica” und verwandter Systeme I. Monatsheft für Mathematik und Physik 38, 173–198. In German, reprinted and English translation: (Gödel, 1986, pages 144-194).
  • Gödel (1986) Gödel, K. 1986. Kurt Gödel – Collected Works. Vol. I – Publications 1929-1936. Oxford University Press, Oxford, UK, and New York, USA. In German with English translations.
  • Golson (1988) Golson, W. G. 1988. Toward a declarative semantics for infinite objects in logic programming. Journal of Logic Programming 5, 2, 151–164.
  • Gordon (1994) Gordon, A. 1994. A tutorial on co-induction and functional programming. In Functional Programming – Proceedings of the 1994 Glasgow Workshop on Computing, K. Hammond, D. N. Turner, and P. M. Sansom, Eds. Springer, 78–95.
  • Gupta et al. (2011) Gupta, G., Saeedloei, N., Vries, B. D., Min, R., Marple, K., and Kluźniak, F. 2011. Infinite computation, co-induction and computational logic. In Proceedings of the 4th International Conference on Algebra and Coalgebra in Computer Science (CALCO), A. Corradini, B. Klin, and C. Cîrstea, Eds. LNCS, vol. 6859. Springer, 40–54.
  • Hansen et al. (2017) Hansen, H. H., Kupke, C., and Rutten, J. J. M. M. 2017. Stream differential equations: Specification formats and solution methods. Logical Methods in Computer Science 13, 1:3, 1–51.
  • Hanus (1994) Hanus, M. 1994. The integration of functions into logic programming: From theory to practice. Journal of Logic Programming 129-20, 583–628.
  • Hein (1992) Hein, J. 1992. Completions of perpetual logic programs. Theoretical Computer Science 99, 1, 65–78.
  • Henderson and Morris (1976) Henderson, P. and Morris, J. H. 1976. A lazy evaluator. In Conference Record of the Third ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages (POPL). Association for Computing Machinery, 95–103.
  • Hoare (1978) Hoare, C. A. R. 1978. Communicating sequential processes. Communications of the ACM 21, 1, 666–677.
  • Hofstadter (1979) Hofstadter, D. 1979. Gödel, Escher, Bach: An Eternal Golden Braid. Basic Books.
  • Jacobs and Rutten (1997) Jacobs, B. and Rutten, J. 1997. A tutorial on (co)algebras and (co)induction. Bulletin of the European Association for Theoretical Computer Science (EATCS) 62, 222–259.
  • Jaffar (1984) Jaffar, J. 1984. Efficient unification over infinite terms. New Generation Computing 2, 3, 207–219.
  • Jaffar et al. (2008) Jaffar, J., Santosa, A. E., and Voicu, R. 2008. A coinduction rule for entailment of recursively defined properties. In Proceedings of the 14th International Conference on Principles ands Practice of Constraint Programming (CP), P. J. Stuckey, Ed. LNCS, vol. 5202. Springer, 493–508.
  • Jaffar and Stuckey (1986) Jaffar, J. and Stuckey, P. J. 1986. Semantics of infinite tree logic programming. Theoretical Computer Science 46, 3, 141–158.
  • Jaume (2002) Jaume, M. 2002. On greatest fixpoint semantics of logic programming. Journal of Logic and Computation 12, 2, 321–342.
  • Jeannin et al. (2017) Jeannin, J.-B., Kozen, D., and Silva, A. 2017. CoCaml: Functional programming with regular coinductive types. Fundamenta Informaticae 150, 3-4, 347–377.
  • Kleene (1938) Kleene, S. C. 1938. On notation for ordinal numbers. The Journal of Symbolic Logic 3, 4, 150–155.
  • Knaster (1928) Knaster, B. 1928. Un théorème sur les fonctions d’ensembles. Annales de la Société Polonaise de Mathématique 6, 133–134.
  • Knuth and Bendix (1967) Knuth, D. E. and Bendix, P. B. 1967. Simple word problems in universal algebra. In Proceedings of a Conference Held at Oxford Under the Auspices of the Science Research Council Atlas Computer Laboratory, J. Leech, Ed. Pergamon, 263–297.
  • Komendantskaya and Li (2017) Komendantskaya, E. and Li, Y. 2017. Productive corecursion in logic programming. Theory and Practice of Logic Programming 17, 5-6, 906–923.
  • Kozen and Silva (2016) Kozen, D. and Silva, A. 2016. Practical coinduction. Mathematical Structures in Computer Science, 1–21.
  • Kupke et al. (2011) Kupke, C., Niqui, M., and Rutten, J. 2011. Stream differential equations: concrete formats for coinductive definitions.
  • Levi and Palamidessi (1988) Levi, G. and Palamidessi, C. 1988. Contributions to the semantics of logic perpetual processes. Acta Informatica 25, 691–711.
  • Li (2018) Li, Y. 2018. Models of coinductive first-order Horn clauses. In Proceedings of the 25th Automated Reasoning Workshop (ARW) – Bridging the Gap between Theory and Practice, M. Jamnik, A. Koutsoukou-Argyraki, E. Ayers, and C. Mangla, Eds. University of Cambridge, United Kingdom, 8–9.
  • Lloyd (1987) Lloyd, J. W. 1987. Foundation of Logic Prograsmming, 2nd ed. Springer.
  • Maher (1988) Maher, M. J. 1988. Complete axiomatizations of the algebras of finite, rational and infinite trees. In Proceedings of the Third Annual Symposium on Logic in Computer Science (LICS). IEEE, 348–357.
  • Mantadelis et al. (2014) Mantadelis, T., Rocha, R., and Moura, P. 2014. Tabling, rational terms, and coinduction finally together! Theory and Practice of Logic Programming (TPLP) 14, Special issue 4-5, 429–443.
  • Martelli and Rossi (1984) Martelli, A. and Rossi, G. 1984. Efficient unification with infinite trees in logic programming. In Proceedings of the International Conference on Fifth Generation Computer Systems (FGCS), I. for New Generation Computer Technology (ICOT), Ed. Ohmsha Ltd. and North-Holland, Tokyo, Japan, and Amsterdam, The Netherland, 202–209.
  • Milner (1971) Milner, R. 1971. An algebraic definition of simulation between programs. In Proceedings of the 2nd International Joint Conferences on Artificial Intelligence (IJCAI). British Computer Society, 481–489.
  • Milner (1980) Milner, R. 1980. A Calculus of Communicating Systems. LNCS, vol. 92. Springer.
  • Moura (2013) Moura, P. 2013. A portable and efficient implementation of coinductive logic programming. In Proceedings of the 15th International Symposium on Practical Aspects of Declarative Languages (PADL). LNCS, vol. 7752. Springer, 77–92.
  • Mukai (1983) Mukai, K. 1983. A unification algorithm for infinite trees. In Proceedings of the 8th International Joint Conference on Artificial Intelligence (IJCAI), Karlsruhe, West Germany, A. Bundy, Ed. Vol. 1. William Kaufmann, Burlington, MA, USA, 547–549.
  • Mycielski and Taylor (1976) Mycielski, J. and Taylor, W. 1976. A compactitication of the algebra of terms. Algebra Universalis 6, 159–163.
  • Palamidessi et al. (1985) Palamidessi, C., Levi, G., and Falaschi, M. 1985. The formal semantics of processes and streams in logic programming. Colloquia Mathematica Societatis Janos Bolyai 42, 363–377.
  • Park (1981) Park, D. 1981. Concurrency on automata and infinite sequences. In Proceedings of the Conference on Theoretical Computer Science, P. Deussen, Ed. LNCS, vol. 104. 167–183.
  • Paulson (1997) Paulson, L. C. 1997. Mechanizing coinduction and corecursion in higher-order logic. Journal of Logic and Computation 7, 2, 175–204.
  • Péter (1961) Péter, R. 1961. Über die Verallgemeinerung der Theorie der rekursiven Funktionen für abstrakte Mengen geeigneter Struktur als Definitionsbereiche. Acta Mathematica Hungarica 12, 3-4, 271–314. In German (“On the generalization of the theory of recursive functions with abstract sets of suitable structures as domains”), presented at “Internationales Symposium der Grundlagen der Mathematik: Infinitische Methoden” (“International Symposium on the Foundations of Mathematics: Infinistic Methods”) on 3 September 1959 in Warsaw, Poland.
  • Plotkin (1972) Plotkin, G. D. 1972. Building-in equational theories. Machine Intelligence, 73–90.
  • Pous and Sangiorgi (2011) Pous, D. and Sangiorgi, D. 2011. Advanced Topics in Bisimulation and Coinduction. Cambridge Tracts in Theoretical Computer Science. Cambridge University Press, Chapter Enhancements of the bisimulation proof method, 233–289.
  • Presburger (1929) Presburger, M. 1929. Über die Vollständigkeit eines gewissen Systems der Arithmetik ganzer Zahlen, in welchem die Addition als einzige Operation hervortritt. In Sprawozdanie z I Kongresu Matematyków Krajów (Proceedings of the First Congress of Mathematicians of the Slavic Countries). Warsaw, Poland, 92–101. In German, English translation: Presburger (1991).
  • Presburger (1991) Presburger, M. 1991. On the completeness of a certain system of arithmetic of whole numbers in which addition occurs as the only operation. History and Philosophy of Logic 12, 2, 225–232.
  • Rutten (2000) Rutten, J. J. . M. M. 2000. Universal coalgebras: a theory of systems. Theoretical Computer Science 249, 1, 3–80.
  • Rutten (2005) Rutten, J. J. M. M. 2005. A coinductive calculus of streams. Mathematical Structures in Computer Science 15, 93–147.
  • Sangiorgi (2009) Sangiorgi, D. 2009. On the origins of bisimulation and coinduction. ACM Transactions on Programming Languages and Systems 31, 4, 15:1–15.
  • Sangiorgi (2012) Sangiorgi, D. 2012. An Introduction to Bisimulation and Coinduction. Cambridge University Press.
  • (72) Siekman, J. Universal unification. In Proceedings of the 7th Conference on Automated Deduction (CADE), R. E. Shostak, Ed. LNCS, vol. 170. Springer, 1–42.
  • Simon et al. (2006) Simon, L., Bansal, A., Mallya, A., and Gupta, G. 2006. Coinductive logic programming. In Proceedings of the International Conference on Logic Programming (ICLP), S. Etalle and M. Truszczyński, Eds. LNCS, vol. 4079. Springer, 330–345.
  • Simon et al. (2007) Simon, L., Bansal, A., Mallya, A., and Gupta, G. 2007. Co-logic programming: Extending logic programming with coinduction. In Proceedings of the International Colloquium on Automata, Languages, and Programming (ICALP). LNCS, vol. 4596. Springer, 472–483.
  • Socher-Ambrosius (1992) Socher-Ambrosius, R. 1992. How to avoid the derivation of redundant clauses in reasoning systems. Journal of Automated Reasoning 9, 77–97.
  • Steele (1977) Steele, G. L. 1977. Debunking the “expensive procedure call” myth or, procedure call implementations considered harmful or, lambda: The ultimate goto. In Proceedings of the 1977 Annual Conference (ACM), J. S. Ketchel and H. Z. Kriloff, Eds. Association for Computing Machinery, New York, USA, 153–162.
  • Tarski (1930) Tarski, A. 1930. Über äquivalenz der mengen in bezug auf eine beliebige klasse von abbildungen. In Proceedings of the International Congress of Mathematicians 1928. Vol. 2. 243–252.
  • Tarski (1955) Tarski, A. 1955. A lattice-theoretical theorem and its applications. Pacific Journal of Mathematics 5, 285–309.
  • Tiwari et al. (2000) Tiwari, A., Bachmair, L., and Ruess, H. 2000. Rigid e-unification revisited. In Proceedings of the 17th International Conference on Automated Deduction (CADE), D. McAllester, Ed. LNCS, vol. 1831. Springer, 220–234.
  • van Emden and Abdallah (1985) van Emden, M. H. and Abdallah, N. M. A. 1985. Top-down semantics of fair computations of logic programs. Journal of Logic Programming 2, 1, 67–75.
  • van Emden and Kowalsi (1976) van Emden, M. H. and Kowalsi, R. A. 1976. The semantics of predicate logic as a programming language. Journal of the ACM 23, 4, 733–742.
  • van Emden and Lloyd (1984) van Emden, M. H. and Lloyd, J. W. 1984. A logical reconstruction of Prolog II. Journal of Logic Programming 2, 143–149.