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