130 total. This simplifies the logic---terms are always defined---but means |
130 total. This simplifies the logic---terms are always defined---but means |
131 that recursive functions must terminate. Otherwise one could define a |
131 that recursive functions must terminate. Otherwise one could define a |
132 function @{prop"f n = f n + (1::nat)"} and conclude \mbox{@{prop"(0::nat) = 1"}} by |
132 function @{prop"f n = f n + (1::nat)"} and conclude \mbox{@{prop"(0::nat) = 1"}} by |
133 subtracting @{term"f n"} on both sides. |
133 subtracting @{term"f n"} on both sides. |
134 |
134 |
135 Isabelle automatic termination checker requires that the arguments of |
135 Isabelle's automatic termination checker requires that the arguments of |
136 recursive calls on the right-hand side must be strictly smaller than the |
136 recursive calls on the right-hand side must be strictly smaller than the |
137 arguments on the left-hand side. In the simplest case, this means that one |
137 arguments on the left-hand side. In the simplest case, this means that one |
138 fixed argument position decreases in size with each recursive call. The size |
138 fixed argument position decreases in size with each recursive call. The size |
139 is measured as the number of constructors (excluding 0-ary ones, e.g.\ @{text |
139 is measured as the number of constructors (excluding 0-ary ones, e.g.\ @{text |
140 Nil}). Lexicographic combinations are also recognised. In more complicated |
140 Nil}). Lexicographic combinations are also recognized. In more complicated |
141 situations, the user may have to prove termination by hand. For details |
141 situations, the user may have to prove termination by hand. For details |
142 see~\cite{Krauss}. |
142 see~\cite{Krauss}. |
143 |
143 |
144 Functions defined with \isacom{fun} come with their own induction schema |
144 Functions defined with \isacom{fun} come with their own induction schema |
145 that mirrors the recursion schema and is derived from the termination |
145 that mirrors the recursion schema and is derived from the termination |
150 "div2 0 = 0" | |
150 "div2 0 = 0" | |
151 "div2 (Suc 0) = Suc 0" | |
151 "div2 (Suc 0) = Suc 0" | |
152 "div2 (Suc(Suc n)) = Suc(div2 n)" |
152 "div2 (Suc(Suc n)) = Suc(div2 n)" |
153 |
153 |
154 text{* does not just define @{const div2} but also proves a |
154 text{* does not just define @{const div2} but also proves a |
155 customised induction rule: |
155 customized induction rule: |
156 \[ |
156 \[ |
157 \inferrule{ |
157 \inferrule{ |
158 \mbox{@{thm (prem 1) div2.induct}}\\ |
158 \mbox{@{thm (prem 1) div2.induct}}\\ |
159 \mbox{@{thm (prem 2) div2.induct}}\\ |
159 \mbox{@{thm (prem 2) div2.induct}}\\ |
160 \mbox{@{thm (prem 3) div2.induct}}} |
160 \mbox{@{thm (prem 3) div2.induct}}} |
161 {\mbox{@{thm (concl) div2.induct[of _ "m"]}}} |
161 {\mbox{@{thm (concl) div2.induct[of _ "m"]}}} |
162 \] |
162 \] |
163 This customised induction rule can simplify inductive proofs. For example, |
163 This customized induction rule can simplify inductive proofs. For example, |
164 *} |
164 *} |
165 |
165 |
166 lemma "div2(n+n) = n" |
166 lemma "div2(n+n) = n" |
167 apply(induction n rule: div2.induct) |
167 apply(induction n rule: div2.induct) |
168 |
168 |
169 txt{* yields the 3 subgoals |
169 txt{* yields the 3 subgoals |
170 @{subgoals[display,margin=65]} |
170 @{subgoals[display,margin=65]} |
171 An application of @{text auto} finishes the proof. |
171 An application of @{text auto} finishes the proof. |
172 Had we used ordinary structural induction on @{text n}, |
172 Had we used ordinary structural induction on @{text n}, |
173 the proof would have needed an additional |
173 the proof would have needed an additional |
174 case distinction in the induction step. |
174 case analysis in the induction step. |
175 |
175 |
176 The general case is often called \concept{computation induction}, |
176 The general case is often called \concept{computation induction}, |
177 because the induction follows the (terminating!) computation. |
177 because the induction follows the (terminating!) computation. |
178 For every defining equation |
178 For every defining equation |
179 \begin{quote} |
179 \begin{quote} |
200 \begin{quote} |
200 \begin{quote} |
201 \emph{Perform induction on argument number $i$\\ |
201 \emph{Perform induction on argument number $i$\\ |
202 if the function is defined by recursion on argument number $i$.} |
202 if the function is defined by recursion on argument number $i$.} |
203 \end{quote} |
203 \end{quote} |
204 The key heuristic, and the main point of this section, is to |
204 The key heuristic, and the main point of this section, is to |
205 \emph{generalise the goal before induction}. |
205 \emph{generalize the goal before induction}. |
206 The reason is simple: if the goal is |
206 The reason is simple: if the goal is |
207 too specific, the induction hypothesis is too weak to allow the induction |
207 too specific, the induction hypothesis is too weak to allow the induction |
208 step to go through. Let us illustrate the idea with an example. |
208 step to go through. Let us illustrate the idea with an example. |
209 |
209 |
210 Function @{const rev} has quadratic worst-case running time |
210 Function @{const rev} has quadratic worst-case running time |
216 (*<*) |
216 (*<*) |
217 apply auto |
217 apply auto |
218 done |
218 done |
219 (*>*) |
219 (*>*) |
220 fun itrev :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
220 fun itrev :: "'a list \<Rightarrow> 'a list \<Rightarrow> 'a list" where |
221 "itrev [] ys = ys" | |
221 "itrev [] ys = ys" | |
222 "itrev (x#xs) ys = itrev xs (x#ys)" |
222 "itrev (x#xs) ys = itrev xs (x#ys)" |
223 |
223 |
224 text{* The behaviour of @{const itrev} is simple: it reverses |
224 text{* The behaviour of @{const itrev} is simple: it reverses |
225 its first argument by stacking its elements onto the second argument, |
225 its first argument by stacking its elements onto the second argument, |
226 and returning that second argument when the first one becomes |
226 and it returns that second argument when the first one becomes |
227 empty. Note that @{const itrev} is tail-recursive: it can be |
227 empty. Note that @{const itrev} is tail-recursive: it can be |
228 compiled into a loop, no stack is necessary for executing it. |
228 compiled into a loop, no stack is necessary for executing it. |
229 |
229 |
230 Naturally, we would like to show that @{const itrev} does indeed reverse |
230 Naturally, we would like to show that @{const itrev} does indeed reverse |
231 its first argument provided the second one is empty: |
231 its first argument provided the second one is empty: |
245 @{subgoals[display,margin=70]} |
245 @{subgoals[display,margin=70]} |
246 The induction hypothesis is too weak. The fixed |
246 The induction hypothesis is too weak. The fixed |
247 argument,~@{term"[]"}, prevents it from rewriting the conclusion. |
247 argument,~@{term"[]"}, prevents it from rewriting the conclusion. |
248 This example suggests a heuristic: |
248 This example suggests a heuristic: |
249 \begin{quote} |
249 \begin{quote} |
250 \emph{Generalise goals for induction by replacing constants by variables.} |
250 \emph{Generalize goals for induction by replacing constants by variables.} |
251 \end{quote} |
251 \end{quote} |
252 Of course one cannot do this na\"{\i}vely: @{prop"itrev xs ys = rev xs"} is |
252 Of course one cannot do this na\"{\i}vely: @{prop"itrev xs ys = rev xs"} is |
253 just not true. The correct generalisation is |
253 just not true. The correct generalization is |
254 *}; |
254 *}; |
255 (*<*)oops;(*>*) |
255 (*<*)oops;(*>*) |
256 lemma "itrev xs ys = rev xs @ ys" |
256 lemma "itrev xs ys = rev xs @ ys" |
257 (*<*)apply(induction xs, auto)(*>*) |
257 (*<*)apply(induction xs, auto)(*>*) |
258 txt{* |
258 txt{* |
259 If @{text ys} is replaced by @{term"[]"}, the right-hand side simplifies to |
259 If @{text ys} is replaced by @{term"[]"}, the right-hand side simplifies to |
260 @{term"rev xs"}, as required. |
260 @{term"rev xs"}, as required. |
261 In this instance it was easy to guess the right generalisation. |
261 In this instance it was easy to guess the right generalization. |
262 Other situations can require a good deal of creativity. |
262 Other situations can require a good deal of creativity. |
263 |
263 |
264 Although we now have two variables, only @{text xs} is suitable for |
264 Although we now have two variables, only @{text xs} is suitable for |
265 induction, and we repeat our proof attempt. Unfortunately, we are still |
265 induction, and we repeat our proof attempt. Unfortunately, we are still |
266 not there: |
266 not there: |
267 @{subgoals[display,margin=65]} |
267 @{subgoals[display,margin=65]} |
268 The induction hypothesis is still too weak, but this time it takes no |
268 The induction hypothesis is still too weak, but this time it takes no |
269 intuition to generalise: the problem is that the @{text ys} |
269 intuition to generalize: the problem is that the @{text ys} |
270 in the induction hypothesis is fixed, |
270 in the induction hypothesis is fixed, |
271 but the induction hypothesis needs to be applied with |
271 but the induction hypothesis needs to be applied with |
272 @{term"a # ys"} instead of @{text ys}. Hence we prove the theorem |
272 @{term"a # ys"} instead of @{text ys}. Hence we prove the theorem |
273 for all @{text ys} instead of a fixed one. We can instruct induction |
273 for all @{text ys} instead of a fixed one. We can instruct induction |
274 to perform this generalisation for us by adding @{text "arbitrary: ys"}. |
274 to perform this generalization for us by adding @{text "arbitrary: ys"}. |
275 *} |
275 *} |
276 (*<*)oops |
276 (*<*)oops |
277 lemma "itrev xs ys = rev xs @ ys" |
277 lemma "itrev xs ys = rev xs @ ys" |
278 (*>*) |
278 (*>*) |
279 apply(induction xs arbitrary: ys) |
279 apply(induction xs arbitrary: ys) |
285 |
285 |
286 apply auto |
286 apply auto |
287 done |
287 done |
288 |
288 |
289 text{* |
289 text{* |
290 This leads to another heuristic for generalisation: |
290 This leads to another heuristic for generalization: |
291 \begin{quote} |
291 \begin{quote} |
292 \emph{Generalise induction by generalising all free |
292 \emph{Generalize induction by generalizing all free |
293 variables\\ {\em(except the induction variable itself)}.} |
293 variables\\ {\em(except the induction variable itself)}.} |
294 \end{quote} |
294 \end{quote} |
295 Generalisation is best performed with @{text"arbitrary: y\<^isub>1 \<dots> y\<^isub>k"}. |
295 Generalization is best performed with @{text"arbitrary: y\<^isub>1 \<dots> y\<^isub>k"}. |
296 This heuristic prevents trivial failures like the one above. |
296 This heuristic prevents trivial failures like the one above. |
297 However, it should not be applied blindly. |
297 However, it should not be applied blindly. |
298 It is not always required, and the additional quantifiers can complicate |
298 It is not always required, and the additional quantifiers can complicate |
299 matters in some cases. The variables that need to be quantified are typically |
299 matters in some cases. The variables that need to be quantified are typically |
300 those that change in recursive calls. |
300 those that change in recursive calls. |
304 So far we have talked a lot about simplifying terms without explaining the concept. \concept{Simplification} means |
304 So far we have talked a lot about simplifying terms without explaining the concept. \concept{Simplification} means |
305 \begin{itemize} |
305 \begin{itemize} |
306 \item using equations $l = r$ from left to right (only), |
306 \item using equations $l = r$ from left to right (only), |
307 \item as long as possible. |
307 \item as long as possible. |
308 \end{itemize} |
308 \end{itemize} |
309 To emphasise the directionality, equations that have been given the |
309 To emphasize the directionality, equations that have been given the |
310 @{text"simp"} attribute are called \concept{simplification} |
310 @{text"simp"} attribute are called \concept{simplification} |
311 rules. Logically, they are still symmetric, but proofs by |
311 rules. Logically, they are still symmetric, but proofs by |
312 simplification use them only in the left-to-right direction. The proof tool |
312 simplification use them only in the left-to-right direction. The proof tool |
313 that performs simplifications is called the \concept{simplifier}. It is the |
313 that performs simplifications is called the \concept{simplifier}. It is the |
314 basis of @{text auto} and other related proof methods. |
314 basis of @{text auto} and other related proof methods. |