doc-src/TutorialI/Fun/fun0.thy
author hoelzl
Mon, 23 Aug 2010 19:35:57 +0200
changeset 38656 d5d342611edb
parent 27167 a99747ccba87
permissions -rw-r--r--
Rewrite the Probability theory. Introduced pinfreal as real numbers with infinity. Use pinfreal as value for measures. Introduces Lebesgue Measure based on the integral in Multivariate Analysis. Proved Radon Nikodym for arbitrary sigma finite measure spaces.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     1
(*<*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     2
theory fun0 imports Main begin
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     3
(*>*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     4
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     5
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     6
\subsection{Definition}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     7
\label{sec:fun-examples}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     8
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
     9
Here is a simple example, the \rmindex{Fibonacci function}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    10
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    11
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    12
fun fib :: "nat \<Rightarrow> nat" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    13
"fib 0 = 0" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    14
"fib (Suc 0) = 1" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    15
"fib (Suc(Suc x)) = fib x + fib (Suc x)"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    16
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    17
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    18
This resembles ordinary functional programming languages. Note the obligatory
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    19
\isacommand{where} and \isa{|}. Command \isacommand{fun} declares and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    20
defines the function in one go. Isabelle establishes termination automatically
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    21
because @{const fib}'s argument decreases in every recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    22
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    23
Slightly more interesting is the insertion of a fixed element
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    24
between any two elements of a list:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    25
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    26
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    27
fun sep :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    28
"sep a []     = []" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    29
"sep a [x]    = [x]" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    30
"sep a (x#y#zs) = x # a # sep a (y#zs)";
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    31
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    32
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    33
This time the length of the list decreases with the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    34
recursive call; the first argument is irrelevant for termination.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    35
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    36
Pattern matching\index{pattern matching!and \isacommand{fun}}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    37
need not be exhaustive and may employ wildcards:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    38
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    39
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    40
fun last :: "'a list \<Rightarrow> 'a" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    41
"last [x]      = x" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    42
"last (_#y#zs) = last (y#zs)"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    43
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    44
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    45
Overlapping patterns are disambiguated by taking the order of equations into
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    46
account, just as in functional programming:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    47
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    48
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    49
fun sep1 :: "'a \<Rightarrow> 'a list \<Rightarrow> 'a list" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    50
"sep1 a (x#y#zs) = x # a # sep1 a (y#zs)" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    51
"sep1 _ xs       = xs"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    52
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    53
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    54
To guarantee that the second equation can only be applied if the first
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    55
one does not match, Isabelle internally replaces the second equation
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    56
by the two possibilities that are left: @{prop"sep1 a [] = []"} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    57
@{prop"sep1 a [x] = [x]"}.  Thus the functions @{const sep} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    58
@{const sep1} are identical.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    59
25263
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
    60
Because of its pattern matching syntax, \isacommand{fun} is also useful
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    61
for the definition of non-recursive functions:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    62
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    63
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    64
fun swap12 :: "'a list \<Rightarrow> 'a list" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    65
"swap12 (x#y#zs) = y#x#zs" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    66
"swap12 zs       = zs"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    67
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    68
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    69
After a function~$f$ has been defined via \isacommand{fun},
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    70
its defining equations (or variants derived from them) are available
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    71
under the name $f$@{text".simps"} as theorems.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    72
For example, look (via \isacommand{thm}) at
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    73
@{thm[source]sep.simps} and @{thm[source]sep1.simps} to see that they define
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    74
the same function. What is more, those equations are automatically declared as
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    75
simplification rules.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    76
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    77
\subsection{Termination}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    78
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    79
Isabelle's automatic termination prover for \isacommand{fun} has a
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    80
fixed notion of the \emph{size} (of type @{typ nat}) of an
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    81
argument. The size of a natural number is the number itself. The size
25339
nipkow
parents: 25265
diff changeset
    82
of a list is its length. For the general case see \S\ref{sec:general-datatype}.
nipkow
parents: 25265
diff changeset
    83
A recursive function is accepted if \isacommand{fun} can
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    84
show that the size of one fixed argument becomes smaller with each
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    85
recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    86
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
    87
More generally, \isacommand{fun} allows any \emph{lexicographic
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    88
combination} of size measures in case there are multiple
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
    89
arguments. For example, the following version of \rmindex{Ackermann's
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    90
function} is accepted: *}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    91
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    92
fun ack2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    93
"ack2 n 0 = Suc n" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    94
"ack2 0 (Suc m) = ack2 (Suc 0) m" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
    95
"ack2 (Suc n) (Suc m) = ack2 (ack2 n (Suc m)) m"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    96
25263
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
    97
text{* The order of arguments has no influence on whether
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    98
\isacommand{fun} can prove termination of a function. For more details
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
    99
see elsewhere~\cite{bulwahnKN07}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   100
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   101
\subsection{Simplification}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   102
\label{sec:fun-simplification}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   103
25265
3a5d33e8a019 tweaked
paulson
parents: 25263
diff changeset
   104
Upon a successful termination proof, the recursion equations become
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   105
simplification rules, just as with \isacommand{primrec}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   106
In most cases this works fine, but there is a subtle
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   107
problem that must be mentioned: simplification may not
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   108
terminate because of automatic splitting of @{text "if"}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   109
\index{*if expressions!splitting of}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   110
Let us look at an example:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   111
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   112
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   113
fun gcd :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
   114
"gcd m n = (if n=0 then m else gcd n (m mod n))"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   115
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   116
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   117
The second argument decreases with each recursive call.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   118
The termination condition
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   119
@{prop[display]"n ~= (0::nat) ==> m mod n < n"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   120
is proved automatically because it is already present as a lemma in
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   121
HOL\@.  Thus the recursion equation becomes a simplification
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   122
rule. Of course the equation is nonterminating if we are allowed to unfold
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   123
the recursive call inside the @{text else} branch, which is why programming
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   124
languages and our simplifier don't do that. Unfortunately the simplifier does
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   125
something else that leads to the same problem: it splits 
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   126
each @{text "if"}-expression unless its
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   127
condition simplifies to @{term True} or @{term False}.  For
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   128
example, simplification reduces
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   129
@{prop[display]"gcd m n = k"}
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   130
in one step to
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   131
@{prop[display]"(if n=0 then m else gcd n (m mod n)) = k"}
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   132
where the condition cannot be reduced further, and splitting leads to
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   133
@{prop[display]"(n=0 --> m=k) & (n ~= 0 --> gcd n (m mod n)=k)"}
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   134
Since the recursive call @{term"gcd n (m mod n)"} is no longer protected by
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   135
an @{text "if"}, it is unfolded again, which leads to an infinite chain of
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   136
simplification steps. Fortunately, this problem can be avoided in many
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   137
different ways.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   138
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   139
The most radical solution is to disable the offending theorem
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   140
@{thm[source]split_if},
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   141
as shown in \S\ref{sec:AutoCaseSplits}.  However, we do not recommend this
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   142
approach: you will often have to invoke the rule explicitly when
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   143
@{text "if"} is involved.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   144
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   145
If possible, the definition should be given by pattern matching on the left
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   146
rather than @{text "if"} on the right. In the case of @{term gcd} the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   147
following alternative definition suggests itself:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   148
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   149
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   150
fun gcd1 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
   151
"gcd1 m 0 = m" |
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
   152
"gcd1 m n = gcd1 n (m mod n)"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   153
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   154
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   155
The order of equations is important: it hides the side condition
25263
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   156
@{prop"n ~= (0::nat)"}.  Unfortunately, not all conditionals can be
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   157
expressed by pattern matching.
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   158
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   159
A simple alternative is to replace @{text "if"} by @{text case}, 
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   160
which is also available for @{typ bool} and is not split automatically:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   161
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   162
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   163
fun gcd2 :: "nat \<Rightarrow> nat \<Rightarrow> nat" where
27015
f8537d69f514 *** empty log message ***
nipkow
parents: 25339
diff changeset
   164
"gcd2 m n = (case n=0 of True \<Rightarrow> m | False \<Rightarrow> gcd2 n (m mod n))"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   165
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   166
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   167
This is probably the neatest solution next to pattern matching, and it is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   168
always available.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   169
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   170
A final alternative is to replace the offending simplification rules by
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   171
derived conditional ones. For @{term gcd} it means we have to prove
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   172
these lemmas:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   173
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   174
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   175
lemma [simp]: "gcd m 0 = m"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   176
apply(simp)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   177
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   178
25261
3dc292be0b54 recdef -> fun
nipkow
parents: 25260
diff changeset
   179
lemma [simp]: "n \<noteq> 0 \<Longrightarrow> gcd m n = gcd n (m mod n)"
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   180
apply(simp)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   181
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   182
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   183
text{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   184
Simplification terminates for these proofs because the condition of the @{text
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   185
"if"} simplifies to @{term True} or @{term False}.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   186
Now we can disable the original simplification rule:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   187
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   188
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   189
declare gcd.simps [simp del]
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   190
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   191
text{*
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   192
\index{induction!recursion|(}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   193
\index{recursion induction|(}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   194
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   195
\subsection{Induction}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   196
\label{sec:fun-induction}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   197
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   198
Having defined a function we might like to prove something about it.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   199
Since the function is recursive, the natural proof principle is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   200
again induction. But this time the structural form of induction that comes
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   201
with datatypes is unlikely to work well --- otherwise we could have defined the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   202
function by \isacommand{primrec}. Therefore \isacommand{fun} automatically
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   203
proves a suitable induction rule $f$@{text".induct"} that follows the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   204
recursion pattern of the particular function $f$. We call this
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   205
\textbf{recursion induction}. Roughly speaking, it
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   206
requires you to prove for each \isacommand{fun} equation that the property
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   207
you are trying to establish holds for the left-hand side provided it holds
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   208
for all recursive calls on the right-hand side. Here is a simple example
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   209
involving the predefined @{term"map"} functional on lists:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   210
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   211
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   212
lemma "map f (sep x xs) = sep (f x) (map f xs)"
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   213
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   214
txt{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   215
Note that @{term"map f xs"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   216
is the result of applying @{term"f"} to all elements of @{term"xs"}. We prove
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   217
this lemma by recursion induction over @{term"sep"}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   218
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   219
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   220
apply(induct_tac x xs rule: sep.induct);
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   221
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   222
txt{*\noindent
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   223
The resulting proof state has three subgoals corresponding to the three
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   224
clauses for @{term"sep"}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   225
@{subgoals[display,indent=0]}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   226
The rest is pure simplification:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   227
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   228
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   229
apply simp_all;
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   230
done
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   231
25263
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   232
text{*\noindent The proof goes smoothly because the induction rule
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   233
follows the recursion of @{const sep}.  Try proving the above lemma by
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   234
structural induction, and you find that you need an additional case
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   235
distinction.
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   236
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   237
In general, the format of invoking recursion induction is
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   238
\begin{quote}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   239
\isacommand{apply}@{text"(induct_tac"} $x@1 \dots x@n$ @{text"rule:"} $f$@{text".induct)"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   240
\end{quote}\index{*induct_tac (method)}%
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   241
where $x@1~\dots~x@n$ is a list of free variables in the subgoal and $f$ the
27167
nipkow
parents: 27015
diff changeset
   242
name of a function that takes $n$ arguments. Usually the subgoal will
25263
b54744935036 *** empty log message ***
nipkow
parents: 25261
diff changeset
   243
contain the term $f x@1 \dots x@n$ but this need not be the case. The
25260
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   244
induction rules do not mention $f$ at all. Here is @{thm[source]sep.induct}:
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   245
\begin{isabelle}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   246
{\isasymlbrakk}~{\isasymAnd}a.~P~a~[];\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   247
~~{\isasymAnd}a~x.~P~a~[x];\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   248
~~{\isasymAnd}a~x~y~zs.~P~a~(y~\#~zs)~{\isasymLongrightarrow}~P~a~(x~\#~y~\#~zs){\isasymrbrakk}\isanewline
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   249
{\isasymLongrightarrow}~P~u~v%
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   250
\end{isabelle}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   251
It merely says that in order to prove a property @{term"P"} of @{term"u"} and
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   252
@{term"v"} you need to prove it for the three cases where @{term"v"} is the
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   253
empty list, the singleton list, and the list with at least two elements.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   254
The final case has an induction hypothesis:  you may assume that @{term"P"}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   255
holds for the tail of that list.
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   256
\index{induction!recursion|)}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   257
\index{recursion induction|)}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   258
*}
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   259
(*<*)
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   260
end
71b2a1fefb84 added Fun
nipkow
parents:
diff changeset
   261
(*>*)