Structural induction

In the last chapter, we have specified two ADTs: $ List$ and $ FIFO$ , as well as one $ FIFO$ implementation relying on lists. The following were open issues:

  • while selecting axioms for $ append$ and $ reverse$ , we claimed that they guarantee certain properties of the ADT hold
  • in showing that the List implementation of the FIFO, we also require a property of lists to hold.

In this lecture we will examine structural induction: a mechanism which generalises mathematical induction and allows us to prove properties of recursively-defined structures such as ADTs.

Let the sort $ T$ designate our datatype.

Let $ O : T$ . Operators such as $ O$ are called nullary constructors: they designate special/specific values of the ADT $ T$ .

Let $ E: X \rightarrow T$ . Operators such as $ E$ are called external constructors: they construct values of $ T$ using only elements foreign to the type $ T$ (in our example $ X$ ).

Let $ I : T \rightarrow T$ or $ I: X \times T \rightarrow T$ or $ I: T\times T\rightarrow T$ . Operators such as $ I$ are called internal constructors: they rely on other values of $ T$ (maybe more than one) in order to build a new value of $ T$ .

This classification is useful for describing structural induction.

Suppose we want to prove a property of the form:

$ \forall t \in T : P(t)$

If $ T$ would interpret the natural numbers, then a proof by induction implies:

  • showing the basis case (t=0)
  • showing the induction step:
    • assume P(t) holds (induction hypothesis); prove that P(t+1) holds

Then, the induction principle guarantees the property to hold for every natural number, since (+1) is the obvious construction step for natural numbers, starting from 0.

To prove a property inductively, it is sufficient to generalise the induction principle, in order to take into account all possible construction steps. Hence:

  • for each nullary constructor O, we need to prove P(O). Each such proof consists in a basis case.
  • for each external constructor E and each value (or sequence of values) e, we need to prove P(E(e)). This is again a basis case
  • for each internal constructor I which takes $ t_1, \ldots, t_n$ as parameter, we need to:
    • make the induction hypothesis $ P(t_i)$ for each $ i$
    • prove $ P(I(t_1,\ldots t_n))$

Prove via structural induction:

  • $ size(append(l1,l2)) = size(l1) + size(l2)$
  • $ reverse(reverse(l)) = l$
  • $ size(l) = size(reverse(l))$
  • $ l \neq Void \rightarrow tail(l++l')=tail(l)++l'$

Let us define the $ sorted$ property over lists: $ sorted:List\rightarrow \mathbb{B}$

  • $ sorted(Void) = true$
  • $ sorted(e:Void) = true$
  • $ sorted(e:e':l) = e < e' \wedge sorted(e':l)$

as well as one basic sorting procedure, insertion-sort. We first define:

$ ins:E\times List \rightarrow List$

  • $ ins(e,Void) = e:Void$
  • $ ins(e',e:l) = e:ins(e',l) \text{ if } e'> e \text{ and } e':e:l \text{ otherwise }$

which inserts an element in a sorted list, and produces a sorted list. Then, we have:

$ sort:List \rightarrow List$

  • $ sort(Void) = Void$
  • $ sort(e:l) = ins(e,sort(l))$

Warm-up

We can use the $ sorted$ definition in order to prove the correctness of insertion-sort. Before doing so, we start with the proof of a basic property $ PSort$ :

$ sorted(e:l) \implies \forall e'\in l: e\leq e'$

First, we formulate the property in the form $ \forall l. P(l)$ , that is:

$ \forall l: sorted(e:l) \implies \forall e'\in l: e\leq e'$

Basis case $ l = Void$ . Since $ l$ contains no elements, the implication trivially holds.

Induction step. $ l = x:l'$ . We prove: $ sorted(e:x:l') \implies \forall e'\in l': e\leq e'$ . Suppose $ sorted(e:x:l')$ is true. By the axioms of $ sorted$ we have:

  • $ e < x$ and
  • $ sorted(x:l')$

Since $ sorted(x:l')$ is true, by the induction hypothesis we have $ \forall e'\in l': x\leq e'$ . Since $ e < x$ , it follows that $ \forall e' \in x:l': e \leq e'$ . The implication has been proved.

Correctness of insertion

We continue with the following property $ PIns$ , which proves that insertion is correct:

$ \forall l: sorted(l) \rightarrow sorted(ins(e,l))$

Basis case ($ l = Void$ ). First of all, $ sorted(Void)$ is trivially true. Therefore $ sorted(ins(e,Void))$ must also be true, which is indeed the case, as it follows immediately from the axioms.

Induction step. ($ l = x:xs$ ). Suppose $ sorted(x:xs) (\star)$ is true. We show that $ sorted(ins(e,x:xs))$ is also true.

Case 1: $ xs = Void$ . Then:

  • $ sorted(ins(e,x:Void)) = $
  • $ sorted(e:x:Void)$ if $ x > e$ or $ sorted(x:e:Void)$ , otherwise. In both situations, the axioms for $ sorted$ are verified.

Case 2: $ xs \neq Void$ . Recall that $ sorted(x:xs)$ is true (the LHS of the implication which we prove), hence: $ x \leq head(xs)$ and $ sorted(xs)$ . From the latter and the induction hypothesis, we have $ sorted(ins(e,xs)) (\star\star)$ .

Then:

  • $ sorted(ins(e,x:xs)) = $
  • Case 2a: $ e > x$ : $ sorted(x:ins(e,xs))$ . Then:
    • from $ (\star)$ and $ PSort$ , we have $ \forall y\in (x:xs): x \leq y$ - x is the smallest element of $ x:xs$ ;
    • but $ e > x$ , hence $ x$ is at least as small as any element of $ ins(e,xs)$ . In particular, $ x \leq head(ins(e,xs))$ (which is well-defined since $ xs\neq Void$ ).
    • from $ (\star\star)$ we have $ sorted(ins(e,xs))$ which concludes the proof for $ sorted(x:ins(e,xs))$ .
  • Case 2b: $ e \leq x$ : $ sorted(e:x:xs)$ . Since $ e \leq x$ is true and $ sorted(x:xs) (\star)$ , the claim is true.

This concludes the proof of our statement.

Correctness of InsertionSort

The correctness of InsertionSort is expressed by: $ \forall l: sorted(sort(l))$

Basis case $ l = Void$ . The proposition follows immediately from the axioms.

Induction step: $ l = x:xs$ . The induction hypothesis is $ sorted(sort(xs))$ . We need to prove:

  • $ sorted(sort(x:xs))=$
  • $ sorted(ins(x,sort(xs))$ . Since $ sorted(sort(xs))$ (induction hypothesis) from $ PIns$ the statement follows immediately.