src/HOL/Induct/Common_Patterns.thy
author wenzelm
Sun, 16 Sep 2007 21:04:45 +0200
changeset 24608 aae1095dbe3b
child 24609 3f238d4987c0
permissions -rw-r--r--
HOL/Induct/Common_Patterns.thy
wenzelm@24608
     1
(*  Title:      HOL/Induct/Common_Patterns.thy
wenzelm@24608
     2
    ID:         $Id$
wenzelm@24608
     3
    Author:     Makarius
wenzelm@24608
     4
*)
wenzelm@24608
     5
wenzelm@24608
     6
header {* Common patterns of induction *}
wenzelm@24608
     7
wenzelm@24608
     8
theory Common_Patterns
wenzelm@24608
     9
imports Main
wenzelm@24608
    10
begin
wenzelm@24608
    11
wenzelm@24608
    12
text {*
wenzelm@24608
    13
  The subsequent Isar proof schemes illustrate common proof patterns
wenzelm@24608
    14
  supported by the generic @{text "induct"} method.
wenzelm@24608
    15
wenzelm@24608
    16
  To demonstrate variations on statement (goal) structure we refer to
wenzelm@24608
    17
  the induction rule of Peano natural numbers: @{thm nat.induct
wenzelm@24608
    18
  [no_vars]}, which is the simplest case of datatype induction.  We
wenzelm@24608
    19
  shall also see more complex (mutual) datatype inductions involving
wenzelm@24608
    20
  several rules.  Working with inductive predicates is similar, but
wenzelm@24608
    21
  involves explicit facts about membership, instead of implicit
wenzelm@24608
    22
  syntactic typing.
wenzelm@24608
    23
*}
wenzelm@24608
    24
wenzelm@24608
    25
wenzelm@24608
    26
subsection {* Variations on statement structure *}
wenzelm@24608
    27
wenzelm@24608
    28
subsubsection {* Local facts and parameters *}
wenzelm@24608
    29
wenzelm@24608
    30
text {*
wenzelm@24608
    31
  Augmenting a problem by additional facts and locally fixed variables
wenzelm@24608
    32
  is a bread-and-butter method in many applications.  This is where
wenzelm@24608
    33
  unwieldy object-level @{text "\<forall>"} and @{text "\<longrightarrow>"} used to occur in
wenzelm@24608
    34
  the past.  The @{text "induct"} method works with primary means of
wenzelm@24608
    35
  the proof language instead.
wenzelm@24608
    36
*}
wenzelm@24608
    37
wenzelm@24608
    38
lemma
wenzelm@24608
    39
  fixes n :: nat
wenzelm@24608
    40
    and x :: 'a
wenzelm@24608
    41
  assumes "A n x"
wenzelm@24608
    42
  shows "P n x" using `A n x`
wenzelm@24608
    43
proof (induct n arbitrary: x)
wenzelm@24608
    44
  case 0
wenzelm@24608
    45
  note prem = `A 0 x`
wenzelm@24608
    46
  show "P 0 x" sorry
wenzelm@24608
    47
next
wenzelm@24608
    48
  case (Suc n)
wenzelm@24608
    49
  note hyp = `\<And>x. A n x \<Longrightarrow> P n x`
wenzelm@24608
    50
    and prem = `A (Suc n) x`
wenzelm@24608
    51
  show "P (Suc n) x" sorry
wenzelm@24608
    52
qed
wenzelm@24608
    53
wenzelm@24608
    54
wenzelm@24608
    55
subsubsection {* Local definitions *}
wenzelm@24608
    56
wenzelm@24608
    57
text {*
wenzelm@24608
    58
  Here the idea is to turn sub-expressions of the problem into a
wenzelm@24608
    59
  defined induction variable.  This is often accompanied with fixing
wenzelm@24608
    60
  of auxiliary parameters in the original expression, otherwise the
wenzelm@24608
    61
  induction step would refer invariably to particular entities.  This
wenzelm@24608
    62
  combination essentially expresses a partially abstracted
wenzelm@24608
    63
  representation of inductive expressions.
wenzelm@24608
    64
*}
wenzelm@24608
    65
wenzelm@24608
    66
lemma
wenzelm@24608
    67
  fixes a :: "'a \<Rightarrow> nat"
wenzelm@24608
    68
  assumes "A (a x)"
wenzelm@24608
    69
  shows "P (a x)" using `A (a x)`
wenzelm@24608
    70
proof (induct n \<equiv> "a x" arbitrary: x)
wenzelm@24608
    71
  case 0
wenzelm@24608
    72
  note prem = `A (a x)`
wenzelm@24608
    73
    and defn = `0 = a x`
wenzelm@24608
    74
  show "P (a x)" sorry
wenzelm@24608
    75
next
wenzelm@24608
    76
  case (Suc n)
wenzelm@24608
    77
  note hyp = `\<And>x. A (a x) \<Longrightarrow> n = a x \<Longrightarrow> P (a x)`
wenzelm@24608
    78
    and prem = `A (a x)`
wenzelm@24608
    79
    and defn = `Suc n = a x`
wenzelm@24608
    80
  show "P (a x)" sorry
wenzelm@24608
    81
qed
wenzelm@24608
    82
wenzelm@24608
    83
text {*
wenzelm@24608
    84
  Observe how the local definition @{text "n = a x"} recurs in the
wenzelm@24608
    85
  inductive cases as @{text "0 = a x"} and @{text "Suc n = a x"},
wenzelm@24608
    86
  according to underlying induction rule.
wenzelm@24608
    87
*}
wenzelm@24608
    88
wenzelm@24608
    89
wenzelm@24608
    90
subsubsection {* Simple simultaneous goals *}
wenzelm@24608
    91
wenzelm@24608
    92
text {*
wenzelm@24608
    93
  The most basic simultaneous induction operates on several goals
wenzelm@24608
    94
  one-by-one, where each case refers to induction hypotheses that are
wenzelm@24608
    95
  duplicated according to the number of conclusions.
wenzelm@24608
    96
*}
wenzelm@24608
    97
wenzelm@24608
    98
lemma
wenzelm@24608
    99
  fixes n :: nat
wenzelm@24608
   100
  shows "P n" and "Q n"
wenzelm@24608
   101
proof (induct n)
wenzelm@24608
   102
  case 0 case 1
wenzelm@24608
   103
  show "P 0" sorry
wenzelm@24608
   104
next
wenzelm@24608
   105
  case 0 case 2
wenzelm@24608
   106
  show "Q 0" sorry
wenzelm@24608
   107
next
wenzelm@24608
   108
  case (Suc n) case 1
wenzelm@24608
   109
  note hyps = `P n` `Q n`
wenzelm@24608
   110
  show "P (Suc n)" sorry
wenzelm@24608
   111
next
wenzelm@24608
   112
  case (Suc n) case 2
wenzelm@24608
   113
  note hyps = `P n` `Q n`
wenzelm@24608
   114
  show "Q (Suc n)" sorry
wenzelm@24608
   115
qed
wenzelm@24608
   116
wenzelm@24608
   117
text {*
wenzelm@24608
   118
  The split into subcases may be deferred as follows -- this is
wenzelm@24608
   119
  particularly relevant for goal statements with local premises.
wenzelm@24608
   120
*}
wenzelm@24608
   121
wenzelm@24608
   122
lemma
wenzelm@24608
   123
  fixes n :: nat
wenzelm@24608
   124
  shows "A n \<Longrightarrow> P n"
wenzelm@24608
   125
    and "B n \<Longrightarrow> Q n"
wenzelm@24608
   126
proof (induct n)
wenzelm@24608
   127
  case 0
wenzelm@24608
   128
  {
wenzelm@24608
   129
    case 1
wenzelm@24608
   130
    note `A 0`
wenzelm@24608
   131
    show "P 0" sorry
wenzelm@24608
   132
  next
wenzelm@24608
   133
    case 2
wenzelm@24608
   134
    note `B 0`
wenzelm@24608
   135
    show "Q 0" sorry
wenzelm@24608
   136
  }
wenzelm@24608
   137
next
wenzelm@24608
   138
  case (Suc n)
wenzelm@24608
   139
  note `A n \<Longrightarrow> P n`
wenzelm@24608
   140
    and `B n \<Longrightarrow> Q n`
wenzelm@24608
   141
  {
wenzelm@24608
   142
    case 1
wenzelm@24608
   143
    note `A (Suc n)`
wenzelm@24608
   144
    show "P (Suc n)" sorry
wenzelm@24608
   145
  next
wenzelm@24608
   146
    case 2
wenzelm@24608
   147
    note `B (Suc n)`
wenzelm@24608
   148
    show "Q (Suc n)" sorry
wenzelm@24608
   149
  }
wenzelm@24608
   150
qed
wenzelm@24608
   151
wenzelm@24608
   152
wenzelm@24608
   153
subsubsection {* Compound simultaneous goals *}
wenzelm@24608
   154
wenzelm@24608
   155
text {*
wenzelm@24608
   156
  The following pattern illustrates the slightly more complex
wenzelm@24608
   157
  situation of simultaneous goals with individual local assumptions.
wenzelm@24608
   158
  In compound simultaneous statements like this, local assumptions
wenzelm@24608
   159
  need to be included into each goal, using @{text "\<Longrightarrow>"} of the Pure
wenzelm@24608
   160
  framework.  In contrast, local parameters do not require separate
wenzelm@24608
   161
  @{text "\<And>"} prefixes here, but may be moved into the common context
wenzelm@24608
   162
  of the whole statement.
wenzelm@24608
   163
*}
wenzelm@24608
   164
wenzelm@24608
   165
lemma
wenzelm@24608
   166
  fixes n :: nat
wenzelm@24608
   167
    and x :: 'a
wenzelm@24608
   168
    and y :: 'b
wenzelm@24608
   169
  shows "A n x \<Longrightarrow> P n x"
wenzelm@24608
   170
    and "B n y \<Longrightarrow> Q n y"
wenzelm@24608
   171
proof (induct n arbitrary: x y)
wenzelm@24608
   172
  case 0
wenzelm@24608
   173
  {
wenzelm@24608
   174
    case 1
wenzelm@24608
   175
    note prem = `A 0 x`
wenzelm@24608
   176
    show "P 0 x" sorry
wenzelm@24608
   177
  }
wenzelm@24608
   178
  {
wenzelm@24608
   179
    case 2
wenzelm@24608
   180
    note prem = `B 0 y`
wenzelm@24608
   181
    show "Q 0 y" sorry
wenzelm@24608
   182
  }
wenzelm@24608
   183
next
wenzelm@24608
   184
  case (Suc n)
wenzelm@24608
   185
  note hyps = `\<And>x. A n x \<Longrightarrow> P n x` `\<And>y. B n y \<Longrightarrow> Q n y`
wenzelm@24608
   186
  then have some_intermediate_result sorry
wenzelm@24608
   187
  {
wenzelm@24608
   188
    case 1
wenzelm@24608
   189
    note prem = `A (Suc n) x`
wenzelm@24608
   190
    show "P (Suc n) x" sorry
wenzelm@24608
   191
  }
wenzelm@24608
   192
  {
wenzelm@24608
   193
    case 2
wenzelm@24608
   194
    note prem = `B (Suc n) y`
wenzelm@24608
   195
    show "Q (Suc n) y" sorry
wenzelm@24608
   196
  }
wenzelm@24608
   197
qed
wenzelm@24608
   198
wenzelm@24608
   199
text {*
wenzelm@24608
   200
  Here @{text "induct"} provides again nested cases with numbered
wenzelm@24608
   201
  sub-cases, which allows to share common parts of the body context.
wenzelm@24608
   202
  In typical applications, there could be a long intermediate proof of
wenzelm@24608
   203
  general consequences of the induction hypotheses, before finishing
wenzelm@24608
   204
  each conclusion separately.
wenzelm@24608
   205
*}
wenzelm@24608
   206
wenzelm@24608
   207
wenzelm@24608
   208
subsection {* Multiple rules *}
wenzelm@24608
   209
wenzelm@24608
   210
text {*
wenzelm@24608
   211
  Multiple induction rules emerge from mutual definitions of
wenzelm@24608
   212
  datatypes, inductive predicates, functions etc.  The @{text
wenzelm@24608
   213
  "induct"} method accepts replicated arguments (with @{text "and"}
wenzelm@24608
   214
  separator), corresponding to each projection of the induction
wenzelm@24608
   215
  principle.
wenzelm@24608
   216
wenzelm@24608
   217
  The goal statement essentially follows the same arrangement,
wenzelm@24608
   218
  although it might be subdivided into simultaneous sub-problems as
wenzelm@24608
   219
  before!
wenzelm@24608
   220
*}
wenzelm@24608
   221
wenzelm@24608
   222
datatype foo = Foo1 nat | Foo2 bar
wenzelm@24608
   223
  and bar = Bar1 bool | Bar2 bazar
wenzelm@24608
   224
  and bazar = Bazar foo
wenzelm@24608
   225
wenzelm@24608
   226
text {*
wenzelm@24608
   227
  The pack of induction rules for this datatype is: @{thm [display]
wenzelm@24608
   228
  foo_bar_bazar.inducts [no_vars]}
wenzelm@24608
   229
wenzelm@24608
   230
  This corresponds to the following basic proof pattern:
wenzelm@24608
   231
*}
wenzelm@24608
   232
wenzelm@24608
   233
lemma
wenzelm@24608
   234
  fixes foo :: foo
wenzelm@24608
   235
    and bar :: bar
wenzelm@24608
   236
    and bazar :: bazar
wenzelm@24608
   237
  shows "P foo"
wenzelm@24608
   238
    and "Q bar"
wenzelm@24608
   239
    and "R bazar"
wenzelm@24608
   240
proof (induct foo and bar and bazar)
wenzelm@24608
   241
  case (Foo1 n)
wenzelm@24608
   242
  show "P (Foo1 n)" sorry
wenzelm@24608
   243
next
wenzelm@24608
   244
  case (Foo2 bar)
wenzelm@24608
   245
  note `Q bar`
wenzelm@24608
   246
  show "P (Foo2 bar)" sorry
wenzelm@24608
   247
next
wenzelm@24608
   248
  case (Bar1 b)
wenzelm@24608
   249
  show "Q (Bar1 b)" sorry
wenzelm@24608
   250
next
wenzelm@24608
   251
  case (Bar2 bazar)
wenzelm@24608
   252
  note `R bazar`
wenzelm@24608
   253
  show "Q (Bar2 bazar)" sorry
wenzelm@24608
   254
next
wenzelm@24608
   255
  case (Bazar foo)
wenzelm@24608
   256
  note `P foo`
wenzelm@24608
   257
  show "R (Bazar foo)" sorry
wenzelm@24608
   258
qed
wenzelm@24608
   259
wenzelm@24608
   260
text {*
wenzelm@24608
   261
  This can be combined with the previous techniques for compound
wenzelm@24608
   262
  statements, e.g.\ like this.
wenzelm@24608
   263
*}
wenzelm@24608
   264
wenzelm@24608
   265
lemma
wenzelm@24608
   266
  fixes x :: 'a and y :: 'b and z :: 'c
wenzelm@24608
   267
    and foo :: foo
wenzelm@24608
   268
    and bar :: bar
wenzelm@24608
   269
    and bazar :: bazar
wenzelm@24608
   270
  shows
wenzelm@24608
   271
    "A x foo \<Longrightarrow> P x foo"
wenzelm@24608
   272
  and
wenzelm@24608
   273
    "B1 y bar \<Longrightarrow> Q1 y bar"
wenzelm@24608
   274
    "B2 y bar \<Longrightarrow> Q2 y bar"
wenzelm@24608
   275
  and
wenzelm@24608
   276
    "C1 z bazar \<Longrightarrow> R1 z bazar"
wenzelm@24608
   277
    "C2 z bazar \<Longrightarrow> R2 z bazar"
wenzelm@24608
   278
    "C3 z bazar \<Longrightarrow> R3 z bazar"
wenzelm@24608
   279
proof (induct foo and bar and bazar arbitrary: x and y and z)
wenzelm@24608
   280
  oops
wenzelm@24608
   281
wenzelm@24608
   282
wenzelm@24608
   283
subsection {* Inductive predicates *}
wenzelm@24608
   284
wenzelm@24608
   285
text {*
wenzelm@24608
   286
  The most basic form of induction involving predicates (or sets)
wenzelm@24608
   287
  essentially eliminates a given membership fact.
wenzelm@24608
   288
*}
wenzelm@24608
   289
wenzelm@24608
   290
inductive Even :: "nat \<Rightarrow> bool" where
wenzelm@24608
   291
  zero: "Even 0"
wenzelm@24608
   292
| double: "Even n \<Longrightarrow> Even (2 * n)"
wenzelm@24608
   293
wenzelm@24608
   294
lemma
wenzelm@24608
   295
  assumes "Even n"
wenzelm@24608
   296
  shows "P n"
wenzelm@24608
   297
  using assms
wenzelm@24608
   298
proof induct
wenzelm@24608
   299
  case zero
wenzelm@24608
   300
  show "P 0" sorry
wenzelm@24608
   301
next
wenzelm@24608
   302
  case (double n)
wenzelm@24608
   303
  note `Even n` and `P n`
wenzelm@24608
   304
  show "P (2 * n)" sorry
wenzelm@24608
   305
qed
wenzelm@24608
   306
wenzelm@24608
   307
text {*
wenzelm@24608
   308
  Alternatively, an initial rule statement may be proven as follows,
wenzelm@24608
   309
  performing ``in-situ'' elimination with explicit rule specification.
wenzelm@24608
   310
*}
wenzelm@24608
   311
wenzelm@24608
   312
lemma "Even n \<Longrightarrow> P n"
wenzelm@24608
   313
proof (induct rule: Even.induct)
wenzelm@24608
   314
  oops
wenzelm@24608
   315
wenzelm@24608
   316
text {*
wenzelm@24608
   317
  Simultaneous goals do not introduce anything new.
wenzelm@24608
   318
*}
wenzelm@24608
   319
wenzelm@24608
   320
lemma
wenzelm@24608
   321
  assumes "Even n"
wenzelm@24608
   322
  shows "P1 n" and "P2 n"
wenzelm@24608
   323
  using assms
wenzelm@24608
   324
proof induct
wenzelm@24608
   325
  case zero
wenzelm@24608
   326
  {
wenzelm@24608
   327
    case 1
wenzelm@24608
   328
    show "P1 0" sorry
wenzelm@24608
   329
  next
wenzelm@24608
   330
    case 2
wenzelm@24608
   331
    show "P2 0" sorry
wenzelm@24608
   332
  }
wenzelm@24608
   333
next
wenzelm@24608
   334
  case (double n)
wenzelm@24608
   335
  note `Even n` and `P1 n` and `P2 n`
wenzelm@24608
   336
  {
wenzelm@24608
   337
    case 1
wenzelm@24608
   338
    show "P1 (2 * n)" sorry
wenzelm@24608
   339
  next
wenzelm@24608
   340
    case 2
wenzelm@24608
   341
    show "P2 (2 * n)" sorry
wenzelm@24608
   342
  }
wenzelm@24608
   343
qed
wenzelm@24608
   344
wenzelm@24608
   345
text {*
wenzelm@24608
   346
  Working with mutual rules requires special care in composing the
wenzelm@24608
   347
  statement as a two-level conjunction, using lists of propositions
wenzelm@24608
   348
  separated by @{text "and"}.  For example:
wenzelm@24608
   349
*}
wenzelm@24608
   350
wenzelm@24608
   351
inductive Evn :: "nat \<Rightarrow> bool" and Odd :: "nat \<Rightarrow> bool"
wenzelm@24608
   352
where
wenzelm@24608
   353
  zero: "Evn 0"
wenzelm@24608
   354
| succ_Evn: "Evn n \<Longrightarrow> Odd (Suc n)"
wenzelm@24608
   355
| succ_Odd: "Odd n \<Longrightarrow> Evn (Suc n)"
wenzelm@24608
   356
wenzelm@24608
   357
lemma "Evn n \<Longrightarrow> P n"
wenzelm@24608
   358
  and "Odd n \<Longrightarrow> Q n"
wenzelm@24608
   359
proof (induct rule: Evn_Odd.inducts)
wenzelm@24608
   360
  case zero
wenzelm@24608
   361
  show "P 0" sorry
wenzelm@24608
   362
next
wenzelm@24608
   363
  case (succ_Evn n)
wenzelm@24608
   364
  note `Evn n` and `P n`
wenzelm@24608
   365
  show "Q (Suc n)" sorry
wenzelm@24608
   366
next
wenzelm@24608
   367
  case (succ_Odd n)
wenzelm@24608
   368
  note `Odd n` and `Q n`
wenzelm@24608
   369
  show "P (Suc n)" sorry
wenzelm@24608
   370
qed
wenzelm@24608
   371
wenzelm@24608
   372
end