doc-src/TutorialI/Advanced/document/Partial.tex
author nipkow
Wed, 07 Mar 2001 15:54:11 +0100
changeset 11196 bb4ede27fcb7
parent 11158 5652018b809a
child 11256 49afcce3bada
permissions -rw-r--r--
*** empty log message ***
     1 %
     2 \begin{isabellebody}%
     3 \def\isabellecontext{Partial}%
     4 %
     5 \begin{isamarkuptext}%
     6 \noindent
     7 Throughout the tutorial we have emphasized the fact that all functions
     8 in HOL are total. Hence we cannot hope to define truly partial
     9 functions. The best we can do are functions that are
    10 \emph{underdefined}\index{underdefined function}:
    11 for certain arguments we only know that a result
    12 exists, but we do not know what it is. When defining functions that are
    13 normally considered partial, underdefinedness turns out to be a very
    14 reasonable alternative.
    15 
    16 We have already seen an instance of underdefinedness by means of
    17 non-exhaustive pattern matching: the definition of \isa{last} in
    18 \S\ref{sec:recdef-examples}. The same is allowed for \isacommand{primrec}%
    19 \end{isamarkuptext}%
    20 \isacommand{consts}\ hd\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharprime}a\ list\ {\isasymRightarrow}\ {\isacharprime}a{\isachardoublequote}\isanewline
    21 \isacommand{primrec}\ {\isachardoublequote}hd\ {\isacharparenleft}x{\isacharhash}xs{\isacharparenright}\ {\isacharequal}\ x{\isachardoublequote}%
    22 \begin{isamarkuptext}%
    23 \noindent
    24 although it generates a warning.
    25 Even ordinary definitions allow underdefinedness, this time by means of
    26 preconditions:%
    27 \end{isamarkuptext}%
    28 \isacommand{constdefs}\ minus\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat\ {\isasymRightarrow}\ nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline
    29 {\isachardoublequote}n\ {\isasymle}\ m\ {\isasymLongrightarrow}\ minus\ m\ n\ {\isasymequiv}\ m\ {\isacharminus}\ n{\isachardoublequote}%
    30 \begin{isamarkuptext}%
    31 The rest of this section is devoted to the question of how to define
    32 partial recursive functions by other means that non-exhaustive pattern
    33 matching.%
    34 \end{isamarkuptext}%
    35 %
    36 \isamarkupsubsubsection{Guarded Recursion%
    37 }
    38 %
    39 \begin{isamarkuptext}%
    40 Neither \isacommand{primrec} nor \isacommand{recdef} allow to
    41 prefix an equation with a condition in the way ordinary definitions do
    42 (see \isa{minus} above). Instead we have to move the condition over
    43 to the right-hand side of the equation. Given a partial function $f$
    44 that should satisfy the recursion equation $f(x) = t$ over its domain
    45 $dom(f)$, we turn this into the \isacommand{recdef}
    46 \begin{isabelle}%
    47 \ \ \ \ \ f\ x\ {\isacharequal}\ {\isacharparenleft}if\ x\ {\isasymin}\ dom\ f\ then\ t\ else\ arbitrary{\isacharparenright}%
    48 \end{isabelle}
    49 where \isa{arbitrary} is a predeclared constant of type \isa{{\isacharprime}a}
    50 which has no definition. Thus we know nothing about its value,
    51 which is ideal for specifying underdefined functions on top of it.
    52 
    53 As a simple example we define division on \isa{nat}:%
    54 \end{isamarkuptext}%
    55 \isacommand{consts}\ divi\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}nat\ {\isasymtimes}\ nat\ {\isasymRightarrow}\ nat{\isachardoublequote}\isanewline
    56 \isacommand{recdef}\ divi\ {\isachardoublequote}measure{\isacharparenleft}{\isasymlambda}{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}{\isachardot}\ m{\isacharparenright}{\isachardoublequote}\isanewline
    57 \ \ {\isachardoublequote}divi{\isacharparenleft}m{\isacharcomma}n{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ n\ {\isacharequal}\ {\isadigit{0}}\ then\ arbitrary\ else\isanewline
    58 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ if\ m\ {\isacharless}\ n\ then\ {\isadigit{0}}\ else\ divi{\isacharparenleft}m{\isacharminus}n{\isacharcomma}n{\isacharparenright}{\isacharplus}{\isadigit{1}}{\isacharparenright}{\isachardoublequote}%
    59 \begin{isamarkuptext}%
    60 \noindent Of course we could also have defined
    61 \isa{divi\ {\isacharparenleft}m{\isacharcomma}\ {\isadigit{0}}{\isacharparenright}} to be some specific number, for example 0. The
    62 latter option is chosen for the predefined \isa{div} function, which
    63 simplifies proofs at the expense of deviating from the
    64 standard mathematical division function.
    65 
    66 As a more substantial example we consider the problem of searching a graph.
    67 For simplicity our graph is given by a function (\isa{f}) of
    68 type \isa{{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a} which
    69 maps each node to its successor, i.e.\ the graph is really a tree.
    70 The task is to find the end of a chain, modelled by a node pointing to
    71 itself. Here is a first attempt:
    72 \begin{isabelle}%
    73 \ \ \ \ \ find\ {\isacharparenleft}f{\isacharcomma}\ x{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ f\ x\ {\isacharequal}\ x\ then\ x\ else\ find\ {\isacharparenleft}f{\isacharcomma}\ f\ x{\isacharparenright}{\isacharparenright}%
    74 \end{isabelle}
    75 This may be viewed as a fixed point finder or as one half of the well known
    76 \emph{Union-Find} algorithm.
    77 The snag is that it may not terminate if \isa{f} has non-trivial cycles.
    78 Phrased differently, the relation%
    79 \end{isamarkuptext}%
    80 \isacommand{constdefs}\ step{\isadigit{1}}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}a\ {\isasymtimes}\ {\isacharprime}a{\isacharparenright}set{\isachardoublequote}\isanewline
    81 \ \ {\isachardoublequote}step{\isadigit{1}}\ f\ {\isasymequiv}\ {\isacharbraceleft}{\isacharparenleft}y{\isacharcomma}x{\isacharparenright}{\isachardot}\ y\ {\isacharequal}\ f\ x\ {\isasymand}\ y\ {\isasymnoteq}\ x{\isacharbraceright}{\isachardoublequote}%
    82 \begin{isamarkuptext}%
    83 \noindent
    84 must be well-founded. Thus we make the following definition:%
    85 \end{isamarkuptext}%
    86 \isacommand{consts}\ find\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isacharparenright}\ {\isasymtimes}\ {\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isachardoublequote}\isanewline
    87 \isacommand{recdef}\ find\ {\isachardoublequote}same{\isacharunderscore}fst\ {\isacharparenleft}{\isasymlambda}f{\isachardot}\ wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}{\isacharparenright}\ step{\isadigit{1}}{\isachardoublequote}\isanewline
    88 \ \ {\isachardoublequote}find{\isacharparenleft}f{\isacharcomma}x{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}\isanewline
    89 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ then\ if\ f\ x\ {\isacharequal}\ x\ then\ x\ else\ find{\isacharparenleft}f{\isacharcomma}\ f\ x{\isacharparenright}\isanewline
    90 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ else\ arbitrary{\isacharparenright}{\isachardoublequote}\isanewline
    91 {\isacharparenleft}\isakeyword{hints}\ recdef{\isacharunderscore}simp{\isacharcolon}same{\isacharunderscore}fst{\isacharunderscore}def\ step{\isadigit{1}}{\isacharunderscore}def{\isacharparenright}%
    92 \begin{isamarkuptext}%
    93 \noindent
    94 The recursion equation itself should be clear enough: it is our aborted
    95 first attempt augmented with a check that there are no non-trivial loops.
    96 
    97 What complicates the termination proof is that the argument of \isa{find}
    98 is a pair. To express the required well-founded relation we employ the
    99 predefined combinator \isa{same{\isacharunderscore}fst} of type
   100 \begin{isabelle}%
   101 \ \ \ \ \ {\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ bool{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}b{\isasymtimes}{\isacharprime}b{\isacharparenright}set{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharparenleft}{\isacharprime}a{\isasymtimes}{\isacharprime}b{\isacharparenright}\ {\isasymtimes}\ {\isacharparenleft}{\isacharprime}a{\isasymtimes}{\isacharprime}b{\isacharparenright}{\isacharparenright}set%
   102 \end{isabelle}
   103 defined as
   104 \begin{isabelle}%
   105 \ \ \ \ \ same{\isacharunderscore}fst\ P\ R\ {\isasymequiv}\ {\isacharbraceleft}{\isacharparenleft}{\isacharparenleft}x{\isacharprime}{\isacharcomma}\ y{\isacharprime}{\isacharparenright}{\isacharcomma}\ x{\isacharcomma}\ y{\isacharparenright}{\isachardot}\ x{\isacharprime}\ {\isacharequal}\ x\ {\isasymand}\ P\ x\ {\isasymand}\ {\isacharparenleft}y{\isacharprime}{\isacharcomma}\ y{\isacharparenright}\ {\isasymin}\ R\ x{\isacharbraceright}%
   106 \end{isabelle}
   107 This combinator is designed for
   108 recursive functions on pairs where the first component of the argument is
   109 passed unchanged to all recursive calls. Given a constraint on the first
   110 component and a relation on the second component, \isa{same{\isacharunderscore}fst} builds the
   111 required relation on pairs.  The theorem
   112 \begin{isabelle}%
   113 \ \ \ \ \ {\isacharparenleft}{\isasymAnd}x{\isachardot}\ P\ x\ {\isasymLongrightarrow}\ wf\ {\isacharparenleft}R\ x{\isacharparenright}{\isacharparenright}\ {\isasymLongrightarrow}\ wf\ {\isacharparenleft}same{\isacharunderscore}fst\ P\ R{\isacharparenright}%
   114 \end{isabelle}
   115 is known to the well-foundedness prover of \isacommand{recdef}.  Thus
   116 well-foundedness of the relation given to \isacommand{recdef} is immediate.
   117 Furthermore, each recursive call descends along that relation: the first
   118 argument stays unchanged and the second one descends along \isa{step{\isadigit{1}}\ f}. The proof merely requires unfolding of some definitions, as specified in
   119 the \isacommand{hints} above.
   120 
   121 Normally you will then derive the following conditional variant of and from
   122 the recursion equation%
   123 \end{isamarkuptext}%
   124 \isacommand{lemma}\ {\isacharbrackleft}simp{\isacharbrackright}{\isacharcolon}\isanewline
   125 \ \ {\isachardoublequote}wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}\ {\isasymLongrightarrow}\ find{\isacharparenleft}f{\isacharcomma}x{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}if\ f\ x\ {\isacharequal}\ x\ then\ x\ else\ find{\isacharparenleft}f{\isacharcomma}\ f\ x{\isacharparenright}{\isacharparenright}{\isachardoublequote}\isanewline
   126 \isacommand{by}\ simp%
   127 \begin{isamarkuptext}%
   128 \noindent and then disable the original recursion equation:%
   129 \end{isamarkuptext}%
   130 \isacommand{declare}\ find{\isachardot}simps{\isacharbrackleft}simp\ del{\isacharbrackright}%
   131 \begin{isamarkuptext}%
   132 We can reason about such underdefined functions just like about any other
   133 recursive function. Here is a simple example of recursion induction:%
   134 \end{isamarkuptext}%
   135 \isacommand{lemma}\ {\isachardoublequote}wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}\ {\isasymlongrightarrow}\ f{\isacharparenleft}find{\isacharparenleft}f{\isacharcomma}x{\isacharparenright}{\isacharparenright}\ {\isacharequal}\ find{\isacharparenleft}f{\isacharcomma}x{\isacharparenright}{\isachardoublequote}\isanewline
   136 \isacommand{apply}{\isacharparenleft}induct{\isacharunderscore}tac\ f\ x\ rule{\isacharcolon}find{\isachardot}induct{\isacharparenright}\isanewline
   137 \isacommand{apply}\ simp\isanewline
   138 \isacommand{done}%
   139 \isamarkupsubsubsection{The {\tt\slshape while} Combinator%
   140 }
   141 %
   142 \begin{isamarkuptext}%
   143 If the recursive function happens to be tail recursive, its
   144 definition becomes a triviality if based on the predefined \isaindexbold{while}
   145 combinator.  The latter lives in the Library theory
   146 \isa{While_Combinator}, which is not part of \isa{Main} but needs to
   147 be included explicitly among the ancestor theories.
   148 
   149 Constant \isa{while} is of type \isa{{\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ bool{\isacharparenright}\ {\isasymRightarrow}\ {\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isacharparenright}\ {\isasymRightarrow}\ {\isacharprime}a}
   150 and satisfies the recursion equation \begin{isabelle}%
   151 \ \ \ \ \ while\ b\ c\ s\ {\isacharequal}\ {\isacharparenleft}if\ b\ s\ then\ while\ b\ c\ {\isacharparenleft}c\ s{\isacharparenright}\ else\ s{\isacharparenright}%
   152 \end{isabelle}
   153 That is, \isa{while\ b\ c\ s} is equivalent to the imperative program
   154 \begin{verbatim}
   155      x := s; while b(x) do x := c(x); return x
   156 \end{verbatim}
   157 In general, \isa{s} will be a tuple (better still: a record). As an example
   158 consider the following definition of function \isa{find} above:%
   159 \end{isamarkuptext}%
   160 \isacommand{constdefs}\ find{\isadigit{2}}\ {\isacharcolon}{\isacharcolon}\ {\isachardoublequote}{\isacharparenleft}{\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isacharparenright}\ {\isasymRightarrow}\ {\isacharprime}a\ {\isasymRightarrow}\ {\isacharprime}a{\isachardoublequote}\isanewline
   161 \ \ {\isachardoublequote}find{\isadigit{2}}\ f\ x\ {\isasymequiv}\isanewline
   162 \ \ \ fst{\isacharparenleft}while\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}{\isachardot}\ x{\isacharprime}\ {\isasymnoteq}\ x{\isacharparenright}\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}{\isachardot}\ {\isacharparenleft}x{\isacharprime}{\isacharcomma}f\ x{\isacharprime}{\isacharparenright}{\isacharparenright}\ {\isacharparenleft}x{\isacharcomma}f\ x{\isacharparenright}{\isacharparenright}{\isachardoublequote}%
   163 \begin{isamarkuptext}%
   164 \noindent
   165 The loop operates on two ``local variables'' \isa{x} and \isa{x{\isacharprime}}
   166 containing the ``current'' and the ``next'' value of function \isa{f}.
   167 They are initalized with the global \isa{x} and \isa{f\ x}. At the
   168 end \isa{fst} selects the local \isa{x}.
   169 
   170 Although the definition of tail recursive functions via \isa{while} avoids
   171 termination proofs, there is no free lunch. When proving properties of
   172 functions defined by \isa{while}, termination rears its ugly head
   173 again. Here is \isa{while{\isacharunderscore}rule}, the well known proof rule for total
   174 correctness of loops expressed with \isa{while}:
   175 \begin{isabelle}%
   176 \ \ \ \ \ {\isasymlbrakk}P\ s{\isacharsemicolon}\ {\isasymAnd}s{\isachardot}\ {\isasymlbrakk}P\ s{\isacharsemicolon}\ b\ s{\isasymrbrakk}\ {\isasymLongrightarrow}\ P\ {\isacharparenleft}c\ s{\isacharparenright}{\isacharsemicolon}\isanewline
   177 \isaindent{\ \ \ \ \ \ \ \ }{\isasymAnd}s{\isachardot}\ {\isasymlbrakk}P\ s{\isacharsemicolon}\ {\isasymnot}\ b\ s{\isasymrbrakk}\ {\isasymLongrightarrow}\ Q\ s{\isacharsemicolon}\ wf\ r{\isacharsemicolon}\isanewline
   178 \isaindent{\ \ \ \ \ \ \ \ }{\isasymAnd}s{\isachardot}\ {\isasymlbrakk}P\ s{\isacharsemicolon}\ b\ s{\isasymrbrakk}\ {\isasymLongrightarrow}\ {\isacharparenleft}c\ s{\isacharcomma}\ s{\isacharparenright}\ {\isasymin}\ r{\isasymrbrakk}\isanewline
   179 \isaindent{\ \ \ \ \ }{\isasymLongrightarrow}\ Q\ {\isacharparenleft}while\ b\ c\ s{\isacharparenright}%
   180 \end{isabelle} \isa{P} needs to be true of
   181 the initial state \isa{s} and invariant under \isa{c} (premises 1
   182 and~2). The post-condition \isa{Q} must become true when leaving the loop
   183 (premise~3). And each loop iteration must descend along a well-founded
   184 relation \isa{r} (premises 4 and~5).
   185 
   186 Let us now prove that \isa{find{\isadigit{2}}} does indeed find a fixed point. Instead
   187 of induction we apply the above while rule, suitably instantiated.
   188 Only the final premise of \isa{while{\isacharunderscore}rule} is left unproved
   189 by \isa{auto} but falls to \isa{simp}:%
   190 \end{isamarkuptext}%
   191 \isacommand{lemma}\ lem{\isacharcolon}\ {\isachardoublequote}{\isasymlbrakk}\ wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}{\isacharsemicolon}\ x{\isacharprime}\ {\isacharequal}\ f\ x\ {\isasymrbrakk}\ {\isasymLongrightarrow}\ \isanewline
   192 \ \ \ {\isasymexists}y{\isachardot}\ while\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}{\isachardot}\ x{\isacharprime}\ {\isasymnoteq}\ x{\isacharparenright}\ {\isacharparenleft}{\isasymlambda}{\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}{\isachardot}\ {\isacharparenleft}x{\isacharprime}{\isacharcomma}f\ x{\isacharprime}{\isacharparenright}{\isacharparenright}\ {\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}\ {\isacharequal}\ {\isacharparenleft}y{\isacharcomma}y{\isacharparenright}\ {\isasymand}\isanewline
   193 \ \ \ \ \ \ \ f\ y\ {\isacharequal}\ y{\isachardoublequote}\isanewline
   194 \isacommand{apply}{\isacharparenleft}rule{\isacharunderscore}tac\ P\ {\isacharequal}\ {\isachardoublequote}{\isasymlambda}{\isacharparenleft}x{\isacharcomma}x{\isacharprime}{\isacharparenright}{\isachardot}\ x{\isacharprime}\ {\isacharequal}\ f\ x{\isachardoublequote}\ \isakeyword{and}\isanewline
   195 \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ r\ {\isacharequal}\ {\isachardoublequote}inv{\isacharunderscore}image\ {\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}\ fst{\isachardoublequote}\ \isakeyword{in}\ while{\isacharunderscore}rule{\isacharparenright}\isanewline
   196 \isacommand{apply}\ auto\isanewline
   197 \isacommand{apply}{\isacharparenleft}simp\ add{\isacharcolon}inv{\isacharunderscore}image{\isacharunderscore}def\ step{\isadigit{1}}{\isacharunderscore}def{\isacharparenright}\isanewline
   198 \isacommand{done}%
   199 \begin{isamarkuptext}%
   200 The theorem itself is a simple consequence of this lemma:%
   201 \end{isamarkuptext}%
   202 \isacommand{theorem}\ {\isachardoublequote}wf{\isacharparenleft}step{\isadigit{1}}\ f{\isacharparenright}\ {\isasymLongrightarrow}\ f{\isacharparenleft}find{\isadigit{2}}\ f\ x{\isacharparenright}\ {\isacharequal}\ find{\isadigit{2}}\ f\ x{\isachardoublequote}\isanewline
   203 \isacommand{apply}{\isacharparenleft}drule{\isacharunderscore}tac\ x\ {\isacharequal}\ x\ \isakeyword{in}\ lem{\isacharparenright}\isanewline
   204 \isacommand{apply}{\isacharparenleft}auto\ simp\ add{\isacharcolon}find{\isadigit{2}}{\isacharunderscore}def{\isacharparenright}\isanewline
   205 \isacommand{done}%
   206 \begin{isamarkuptext}%
   207 Let us conclude this section on partial functions by a
   208 discussion of the merits of the \isa{while} combinator. We have
   209 already seen that the advantage (if it is one) of not having to
   210 provide a termintion argument when defining a function via \isa{while} merely puts off the evil hour. On top of that, tail recursive
   211 functions tend to be more complicated to reason about. So why use
   212 \isa{while} at all? The only reason is executability: the recursion
   213 equation for \isa{while} is a directly executable functional
   214 program. This is in stark contrast to guarded recursion as introduced
   215 above which requires an explicit test \isa{x\ {\isasymin}\ dom\ f} in the
   216 function body.  Unless \isa{dom} is trivial, this leads to a
   217 definition that is impossible to execute or prohibitively slow.
   218 Thus, if you are aiming for an efficiently executable definition
   219 of a partial function, you are likely to need \isa{while}.%
   220 \end{isamarkuptext}%
   221 \end{isabellebody}%
   222 %%% Local Variables:
   223 %%% mode: latex
   224 %%% TeX-master: "root"
   225 %%% End: