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