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