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