doc-src/TutorialI/Advanced/Partial.thy
changeset 10885 90695f46440b
parent 10654 458068404143
child 11149 e258b536a137
equal deleted inserted replaced
10884:2995639c6a09 10885:90695f46440b
    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(*>*)