doc-src/TutorialI/IsarOverview/Isar/Induction.thy
author nipkow
Mon, 30 Sep 2002 16:50:39 +0200
changeset 13613 531f1f524848
child 13619 584291949c23
permissions -rw-r--r--
*** empty log message ***
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13613
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     1
(*<*)theory Induction = Main:(*>*)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     2
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     3
section{*Case distinction and induction \label{sec:Induct}*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     4
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     5
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     6
subsection{*Case distinction*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     7
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     8
text{* We have already met the @{text cases} method for performing
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
     9
binary case splits. Here is another example: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    10
lemma "P \<or> \<not> P"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    11
proof cases
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    12
  assume "P" thus ?thesis ..
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    13
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    14
  assume "\<not> P" thus ?thesis ..
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    15
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    16
text{*\noindent Note that the two cases must come in this order.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    17
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    18
This form is appropriate if @{term P} is textually small.  However, if
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    19
@{term P} is large, we don't want to repeat it. This can be avoided by
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    20
the following idiom *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    21
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    22
lemma "P \<or> \<not> P"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    23
proof (cases "P")
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    24
  case True thus ?thesis ..
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    25
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    26
  case False thus ?thesis ..
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    27
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    28
text{*\noindent which is simply a shorthand for the previous
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    29
proof. More precisely, the phrases \isakeyword{case}~@{prop
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    30
True}/@{prop False} abbreviate the corresponding assumptions @{prop P}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    31
and @{prop"\<not>P"}. In contrast to the previous proof we can prove the cases
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    32
in arbitrary order.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    33
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    34
The same game can be played with other datatypes, for example lists:
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    35
*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    36
(*<*)declare length_tl[simp del](*>*)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    37
lemma "length(tl xs) = length xs - 1"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    38
proof (cases xs)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    39
  case Nil thus ?thesis by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    40
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    41
  case Cons thus ?thesis by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    42
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    43
text{*\noindent Here \isakeyword{case}~@{text Nil} abbreviates
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    44
\isakeyword{assume}~@{prop"xs = []"} and \isakeyword{case}~@{text Cons}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    45
abbreviates \isakeyword{fix}~@{text"? ??"}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    46
\isakeyword{assume}~@{text"xs = ? # ??"} where @{text"?"} and @{text"??"}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    47
stand for variable names that have been chosen by the system.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    48
Therefore we cannot
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    49
refer to them (this would lead to obscure proofs) and have not even shown
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    50
them. Luckily, this proof is simple enough we do not need to refer to them.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    51
However, sometimes one may have to. Hence Isar offers a simple scheme for
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    52
naming those variables: replace the anonymous @{text Cons} by, for example,
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    53
@{text"(Cons y ys)"}, which abbreviates \isakeyword{fix}~@{text"y ys"}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    54
\isakeyword{assume}~@{text"xs = Cons y ys"}, i.e.\ @{prop"xs = y # ys"}. Here
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    55
is a (somewhat contrived) example: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    56
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    57
lemma "length(tl xs) = length xs - 1"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    58
proof (cases xs)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    59
  case Nil thus ?thesis by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    60
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    61
  case (Cons y ys)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    62
  hence "length(tl xs) = length ys  \<and>  length xs = length ys + 1"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    63
    by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    64
  thus ?thesis by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    65
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    66
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    67
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    68
subsection{*Structural induction*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    69
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    70
text{* We start with a simple inductive proof where both cases are proved automatically: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    71
lemma "2 * (\<Sum>i<n+1. i) = n*(n+1)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    72
by (induct n, simp_all)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    73
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    74
text{*\noindent If we want to expose more of the structure of the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    75
proof, we can use pattern matching to avoid having to repeat the goal
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    76
statement: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    77
lemma "2 * (\<Sum>i<n+1. i) = n*(n+1)" (is "?P n")
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    78
proof (induct n)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    79
  show "?P 0" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    80
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    81
  fix n assume "?P n"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    82
  thus "?P(Suc n)" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    83
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    84
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    85
text{* \noindent We could refine this further to show more of the equational
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    86
proof. Instead we explore the same avenue as for case distinctions:
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    87
introducing context via the \isakeyword{case} command: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    88
lemma "2 * (\<Sum>i<n+1. i) = n*(n+1)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    89
proof (induct n)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    90
  case 0 show ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    91
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    92
  case Suc thus ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    93
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    94
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    95
text{* \noindent The implicitly defined @{text ?case} refers to the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    96
corresponding case to be proved, i.e.\ @{text"?P 0"} in the first case and
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    97
@{text"?P(Suc n)"} in the second case. Context \isakeyword{case}~@{text 0} is
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    98
empty whereas \isakeyword{case}~@{text Suc} assumes @{text"?P n"}. Again we
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
    99
have the same problem as with case distinctions: we cannot refer to an anonymous @{term n}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   100
in the induction step because it has not been introduced via \isakeyword{fix}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   101
(in contrast to the previous proof). The solution is the same as above:
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   102
replace @{term Suc} by @{text"(Suc i)"}: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   103
lemma fixes n::nat shows "n < n*n + 1"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   104
proof (induct n)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   105
  case 0 show ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   106
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   107
  case (Suc i) thus "Suc i < Suc i * Suc i + 1" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   108
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   109
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   110
text{* \noindent Of course we could again have written
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   111
\isakeyword{thus}~@{text ?case} instead of giving the term explicitly
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   112
but we wanted to use @{term i} somewhere. *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   113
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   114
subsection{*Induction formulae involving @{text"\<And>"} or @{text"\<Longrightarrow>"}*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   115
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   116
text{* Let us now consider the situation where the goal to be proved contains
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   117
@{text"\<And>"} or @{text"\<Longrightarrow>"}, say @{prop"\<And>x. P x \<Longrightarrow> Q x"} --- motivation and a
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   118
real example follow shortly.  This means that in each case of the induction,
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   119
@{text ?case} would be of the same form @{prop"\<And>x. P' x \<Longrightarrow> Q' x"}.  Thus the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   120
first proof steps will be the canonical ones, fixing @{text x} and assuming
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   121
@{prop"P' x"}. To avoid this tedium, induction performs these steps
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   122
automatically: for example in case @{text"(Suc n)"}, @{text ?case} is only
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   123
@{prop"Q' x"} whereas the assumptions (named @{term Suc}) contain both the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   124
usual induction hypothesis \emph{and} @{prop"P' x"}. To fix the name of the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   125
bound variable @{term x} you may write @{text"(Suc n x)"}, thus abbreviating
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   126
\isakeyword{fix}~@{term x}.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   127
It should be clear how this example generalizes to more complex formulae.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   128
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   129
As a concrete example we will now prove complete induction via
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   130
structural induction: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   131
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   132
lemma assumes A: "(\<And>n. (\<And>m. m < n \<Longrightarrow> P m) \<Longrightarrow> P n)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   133
  shows "P(n::nat)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   134
proof (rule A)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   135
  show "\<And>m. m < n \<Longrightarrow> P m"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   136
  proof (induct n)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   137
    case 0 thus ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   138
  next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   139
    case (Suc n m)    -- {*@{text"?m < n \<Longrightarrow> P ?m"}  and  @{prop"m < Suc n"}*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   140
    show ?case       -- {*@{term ?case}*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   141
    proof cases
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   142
      assume eq: "m = n"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   143
      from Suc A have "P n" by blast
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   144
      with eq show "P m" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   145
    next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   146
      assume "m \<noteq> n"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   147
      with Suc have "m < n" by arith
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   148
      thus "P m" by(rule Suc)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   149
    qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   150
  qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   151
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   152
text{* \noindent Given the explanations above and the comments in
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   153
the proof text, the proof should be quite readable.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   154
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   155
The statement of the lemma is interesting because it deviates from the style in
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   156
the Tutorial~\cite{LNCS2283}, which suggests to introduce @{text"\<forall>"} or
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   157
@{text"\<longrightarrow>"} into a theorem to strengthen it for induction. In structured Isar
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   158
proofs we can use @{text"\<And>"} and @{text"\<Longrightarrow>"} instead. This simplifies the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   159
proof and means we do not have to convert between the two kinds of
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   160
connectives.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   161
*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   162
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   163
subsection{*Rule induction*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   164
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   165
text{* We define our own version of reflexive transitive closure of a
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   166
relation *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   167
consts rtc :: "('a \<times> 'a)set \<Rightarrow> ('a \<times> 'a)set"   ("_*" [1000] 999)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   168
inductive "r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   169
intros
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   170
refl:  "(x,x) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   171
step:  "\<lbrakk> (x,y) \<in> r; (y,z) \<in> r* \<rbrakk> \<Longrightarrow> (x,z) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   172
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   173
text{* \noindent and prove that @{term"r*"} is indeed transitive: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   174
lemma assumes A: "(x,y) \<in> r*" shows "(y,z) \<in> r* \<Longrightarrow> (x,z) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   175
using A
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   176
proof induct
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   177
  case refl thus ?case .
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   178
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   179
  case step thus ?case by(blast intro: rtc.step)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   180
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   181
text{*\noindent Rule induction is triggered by a fact $(x_1,\dots,x_n)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   182
\in R$ piped into the proof, here \isakeyword{using}~@{text A}. The
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   183
proof itself follows the inductive definition very
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   184
closely: there is one case for each rule, and it has the same name as
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   185
the rule, analogous to structural induction.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   186
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   187
However, this proof is rather terse. Here is a more readable version:
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   188
*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   189
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   190
lemma assumes A: "(x,y) \<in> r*" and B: "(y,z) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   191
  shows "(x,z) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   192
proof -
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   193
  from A B show ?thesis
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   194
  proof induct
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   195
    fix x assume "(x,z) \<in> r*"  -- {*@{text B}[@{text y} := @{text x}]*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   196
    thus "(x,z) \<in> r*" .
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   197
  next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   198
    fix x' x y
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   199
    assume 1: "(x',x) \<in> r" and
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   200
           IH: "(y,z) \<in> r* \<Longrightarrow> (x,z) \<in> r*" and
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   201
           B:  "(y,z) \<in> r*"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   202
    from 1 IH[OF B] show "(x',z) \<in> r*" by(rule rtc.step)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   203
  qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   204
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   205
text{*\noindent We start the proof with \isakeyword{from}~@{text"A
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   206
B"}. Only @{text A} is ``consumed'' by the induction step.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   207
Since @{text B} is left over we don't just prove @{text
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   208
?thesis} but @{text"B \<Longrightarrow> ?thesis"}, just as in the previous proof. The
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   209
base case is trivial. In the assumptions for the induction step we can
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   210
see very clearly how things fit together and permit ourselves the
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   211
obvious forward step @{text"IH[OF B]"}. *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   212
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   213
subsection{*More induction*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   214
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   215
text{* We close the section by demonstrating how arbitrary induction rules
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   216
are applied. As a simple example we have chosen recursion induction, i.e.\
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   217
induction based on a recursive function definition. The example is an unusual
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   218
definition of rotation: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   219
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   220
consts rot :: "'a list \<Rightarrow> 'a list"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   221
recdef rot "measure length"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   222
"rot [] = []"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   223
"rot [x] = [x]"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   224
"rot (x#y#zs) = y # rot(x#zs)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   225
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   226
text{* In the first proof we set up each case explicitly, merely using
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   227
pattern matching to abbreviate the statement: *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   228
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   229
lemma "length(rot xs) = length xs" (is "?P xs")
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   230
proof (induct xs rule: rot.induct)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   231
  show "?P []" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   232
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   233
  fix x show "?P [x]" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   234
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   235
  fix x y zs assume "?P (x#zs)"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   236
  thus "?P (x#y#zs)" by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   237
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   238
text{*\noindent
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   239
This proof skeleton works for arbitrary induction rules, not just
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   240
@{thm[source]rot.induct}.
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   241
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   242
In the following proof we rely on a default naming scheme for cases: they are
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   243
called 1, 2, etc, unless they have been named explicitly. The latter happens
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   244
only with datatypes and inductively defined sets, but not with recursive
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   245
functions. *}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   246
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   247
lemma "xs \<noteq> [] \<Longrightarrow> rot xs = tl xs @ [hd xs]"
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   248
proof (induct xs rule: rot.induct)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   249
  case 1 thus ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   250
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   251
  case 2 show ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   252
next
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   253
  case 3 thus ?case by simp
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   254
qed
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   255
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   256
text{*\noindent Why can case 2 get away with \isakeyword{show} instead of
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   257
\isakeyword{thus}?
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   258
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   259
Of course both proofs are so simple that they can be condensed to*}
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   260
(*<*)lemma "xs \<noteq> [] \<Longrightarrow> rot xs = tl xs @ [hd xs]"(*>*)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   261
by (induct xs rule: rot.induct, simp_all)
531f1f524848 *** empty log message ***
nipkow
parents:
diff changeset
   262
(*<*)end(*>*)