32 The rest of this section is devoted to the question of how to define |
32 The rest of this section is devoted to the question of how to define |
33 partial recursive functions by other means that non-exhaustive pattern |
33 partial recursive functions by other means that non-exhaustive pattern |
34 matching. |
34 matching. |
35 *} |
35 *} |
36 |
36 |
37 subsubsection{*Guarded recursion*} |
37 subsubsection{*Guarded Recursion*} |
38 |
38 |
39 text{* Neither \isacommand{primrec} nor \isacommand{recdef} allow to |
39 text{* Neither \isacommand{primrec} nor \isacommand{recdef} allow to |
40 prefix an equation with a condition in the way ordinary definitions do |
40 prefix an equation with a condition in the way ordinary definitions do |
41 (see @{term minus} above). Instead we have to move the condition over |
41 (see @{term minus} above). Instead we have to move the condition over |
42 to the right-hand side of the equation. Given a partial function $f$ |
42 to the right-hand side of the equation. Given a partial function $f$ |
56 if m < n then 0 else divi(m-n,n)+1)" |
56 if m < n then 0 else divi(m-n,n)+1)" |
57 |
57 |
58 text{*\noindent Of course we could also have defined |
58 text{*\noindent Of course we could also have defined |
59 @{term"divi(m,0)"} to be some specific number, for example 0. The |
59 @{term"divi(m,0)"} to be some specific number, for example 0. The |
60 latter option is chosen for the predefined @{text div} function, which |
60 latter option is chosen for the predefined @{text div} function, which |
61 simplifies proofs at the expense of moving further away from the |
61 simplifies proofs at the expense of deviating from the |
62 standard mathematical divison function. |
62 standard mathematical division function. |
63 |
63 |
64 As a more substantial example we consider the problem of searching a graph. |
64 As a more substantial example we consider the problem of searching a graph. |
65 For simplicity our graph is given by a function (@{term f}) of |
65 For simplicity our graph is given by a function (@{term f}) of |
66 type @{typ"'a \<Rightarrow> 'a"} which |
66 type @{typ"'a \<Rightarrow> 'a"} which |
67 maps each node to its successor, and the task is to find the end of a chain, |
67 maps each node to its successor, and the task is to find the end of a chain, |
128 lemma "wf(step1 f) \<longrightarrow> f(find(f,x)) = find(f,x)" |
128 lemma "wf(step1 f) \<longrightarrow> f(find(f,x)) = find(f,x)" |
129 apply(induct_tac f x rule:find.induct); |
129 apply(induct_tac f x rule:find.induct); |
130 apply simp |
130 apply simp |
131 done |
131 done |
132 |
132 |
133 subsubsection{*The {\tt\slshape while} combinator*} |
133 subsubsection{*The {\tt\slshape while} Combinator*} |
134 |
134 |
135 text{*If the recursive function happens to be tail recursive, its |
135 text{*If the recursive function happens to be tail recursive, its |
136 definition becomes a triviality if based on the predefined \isaindexbold{while} |
136 definition becomes a triviality if based on the predefined \isaindexbold{while} |
137 combinator. The latter lives in the library theory |
137 combinator. The latter lives in the Library theory |
138 \isa{While_Combinator}, which is not part of @{text Main} but needs to |
138 \isa{While_Combinator}, which is not part of @{text Main} but needs to |
139 be included explicitly among the ancestor theories. |
139 be included explicitly among the ancestor theories. |
140 |
140 |
141 Constant @{term while} is of type @{text"('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a"} |
141 Constant @{term while} is of type @{text"('a \<Rightarrow> bool) \<Rightarrow> ('a \<Rightarrow> 'a) \<Rightarrow> 'a"} |
142 and satisfies the recursion equation @{thm[display]while_unfold[no_vars]} |
142 and satisfies the recursion equation @{thm[display]while_unfold[no_vars]} |
164 termination rears its ugly head again. Here is |
164 termination rears its ugly head again. Here is |
165 @{thm[source]while_rule}, the well known proof rule for total |
165 @{thm[source]while_rule}, the well known proof rule for total |
166 correctness of loops expressed with @{term while}: |
166 correctness of loops expressed with @{term while}: |
167 @{thm[display,margin=50]while_rule[no_vars]} @{term P} needs to be |
167 @{thm[display,margin=50]while_rule[no_vars]} @{term P} needs to be |
168 true of the initial state @{term s} and invariant under @{term c} |
168 true of the initial state @{term s} and invariant under @{term c} |
169 (premises 1 and 2).The post-condition @{term Q} must become true when |
169 (premises 1 and~2). The post-condition @{term Q} must become true when |
170 leaving the loop (premise 3). And each loop iteration must descend |
170 leaving the loop (premise~3). And each loop iteration must descend |
171 along a well-founded relation @{term r} (premises 4 and 5). |
171 along a well-founded relation @{term r} (premises 4 and~5). |
172 |
172 |
173 Let us now prove that @{term find2} does indeed find a fixed point. Instead |
173 Let us now prove that @{term find2} does indeed find a fixed point. Instead |
174 of induction we apply the above while rule, suitably instantiated. |
174 of induction we apply the above while rule, suitably instantiated. |
175 Only the final premise of @{thm[source]while_rule} is left unproved |
175 Only the final premise of @{thm[source]while_rule} is left unproved |
176 by @{text auto} but falls to @{text simp}: |
176 by @{text auto} but falls to @{text simp}: |
177 *} |
177 *} |
178 |
178 |
179 lemma lem: "\<lbrakk> wf(step1 f); x' = f x \<rbrakk> \<Longrightarrow> \<exists>y y'. |
179 lemma lem: "\<lbrakk> wf(step1 f); x' = f x \<rbrakk> \<Longrightarrow> |
180 while (\<lambda>(x,x'). x' \<noteq> x) (\<lambda>(x,x'). (x',f x')) (x,x') = (y,y') \<and> |
180 \<exists>y. while (\<lambda>(x,x'). x' \<noteq> x) (\<lambda>(x,x'). (x',f x')) (x,x') = (y,y) \<and> |
181 y' = y \<and> f y = y" |
181 f y = y" |
182 apply(rule_tac P = "\<lambda>(x,x'). x' = f x" and |
182 apply(rule_tac P = "\<lambda>(x,x'). x' = f x" and |
183 r = "inv_image (step1 f) fst" in while_rule); |
183 r = "inv_image (step1 f) fst" in while_rule); |
184 apply auto |
184 apply auto |
185 apply(simp add:inv_image_def step1_def) |
185 apply(simp add:inv_image_def step1_def) |
186 done |
186 done |
203 @{term while} at all? The only reason is executability: the recursion |
203 @{term while} at all? The only reason is executability: the recursion |
204 equation for @{term while} is a directly executable functional |
204 equation for @{term while} is a directly executable functional |
205 program. This is in stark contrast to guarded recursion as introduced |
205 program. This is in stark contrast to guarded recursion as introduced |
206 above which requires an explicit test @{prop"x \<in> dom f"} in the |
206 above which requires an explicit test @{prop"x \<in> dom f"} in the |
207 function body. Unless @{term dom} is trivial, this leads to a |
207 function body. Unless @{term dom} is trivial, this leads to a |
208 definition which is either not at all executable or prohibitively |
208 definition that is impossible to execute (or prohibitively slow). |
209 expensive. Thus, if you are aiming for an efficiently executable definition |
209 Thus, if you are aiming for an efficiently executable definition |
210 of a partial function, you are likely to need @{term while}. |
210 of a partial function, you are likely to need @{term while}. |
211 *} |
211 *} |
212 |
212 |
213 (*<*)end(*>*) |
213 (*<*)end(*>*) |