5 text{* Function \isa{rev} has quadratic worst-case running time
6 because it calls function \isa{\at} for each element of the list and
7 \isa{\at} is linear in its first argument. A linear time version of
8 \isa{rev} reqires an extra argument where the result is accumulated
9 gradually, using only \isa{\#}:*}
11 consts itrev :: "'a list \\<Rightarrow> 'a list \\<Rightarrow> 'a list";
14 "itrev (x#xs) ys = itrev xs (x#ys)";
16 text{*\noindent The behaviour of \isa{itrev} is simple: it reverses
17 its first argument by stacking its elements onto the second argument,
18 and returning that second argument when the first one becomes
19 empty. Note that \isa{itrev} is tail-recursive, i.e.\ it can be
22 Naturally, we would like to show that \isa{itrev} does indeed reverse
23 its first argument provided the second one is empty: *};
25 lemma "itrev xs [] = rev xs";
28 There is no choice as to the induction variable, and we immediately simplify:
31 apply(induct_tac xs, auto);
34 Unfortunately, this is not a complete success:
36 ~1.~\dots~itrev~list~[]~=~rev~list~{\isasymLongrightarrow}~itrev~list~[a]~=~rev~list~@~[a]%
38 Just as predicted above, the overall goal, and hence the induction
39 hypothesis, is too weak to solve the induction step because of the fixed
40 \isa{[]}. The corresponding heuristic:
42 {\em 3. Generalize goals for induction by replacing constants by variables.}
45 Of course one cannot do this na\"{\i}vely: \isa{itrev xs ys = rev xs} is
46 just not true---the correct generalization is
49 lemma "itrev xs ys = rev xs @ ys";
52 If \isa{ys} is replaced by \isa{[]}, the right-hand side simplifies to
53 @{term"rev xs"}, just as required.
55 In this particular instance it was easy to guess the right generalization,
56 but in more complex situations a good deal of creativity is needed. This is
57 the main source of complications in inductive proofs.
59 Although we now have two variables, only \isa{xs} is suitable for
60 induction, and we repeat our above proof attempt. Unfortunately, we are still
63 ~1.~{\isasymAnd}a~list.\isanewline
64 ~~~~~~~itrev~list~ys~=~rev~list~@~ys~{\isasymLongrightarrow}\isanewline
65 ~~~~~~~itrev~list~(a~\#~ys)~=~rev~list~@~a~\#~ys%
67 The induction hypothesis is still too weak, but this time it takes no
68 intuition to generalize: the problem is that \isa{ys} is fixed throughout
69 the subgoal, but the induction hypothesis needs to be applied with
70 @{term"a # ys"} instead of \isa{ys}. Hence we prove the theorem
71 for all \isa{ys} instead of a fixed one:
74 lemma "\\<forall>ys. itrev xs ys = rev xs @ ys";
77 This time induction on \isa{xs} followed by simplification succeeds. This
78 leads to another heuristic for generalization:
80 {\em 4. Generalize goals for induction by universally quantifying all free
81 variables {\em(except the induction variable itself!)}.}
83 This prevents trivial failures like the above and does not change the
84 provability of the goal. Because it is not always required, and may even
85 complicate matters in some cases, this heuristic is often not
90 by(induct_tac xs, simp, simp);