Structural induction
Motivation
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.
Classification of operators
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.
Structural induction scheme
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))$
Exercises
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'$
Proving implications via structural induction
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.