src/HOL/ex/Rewrite_Examples.thy
author wenzelm
Mon, 23 Mar 2015 14:56:52 +0100
changeset 59781 a71dbf3481a2
parent 59739 4ed50ebf5d36
child 60047 58e5b16cbd94
permissions -rw-r--r--
tuned;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
59739
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     1
theory Rewrite_Examples
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     2
imports Main "~~/src/HOL/Library/Rewrite"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     3
begin
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     4
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     5
section \<open>The rewrite Proof Method by Example\<close>
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     6
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     7
(* This file is intended to give an overview over
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     8
   the features of the pattern-based rewrite proof method.
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
     9
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    10
   See also https://www21.in.tum.de/~noschinl/Pattern-2014/
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    11
*)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    12
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    13
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    14
  fixes a::int and b::int and c::int
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    15
  assumes "P (b + a)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    16
  shows "P (a + b)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    17
by (rewrite at "a + b" add.commute)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    18
   (rule assms)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    19
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    20
(* Selecting a specific subterm in a large, ambiguous term. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    21
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    22
  fixes a b c :: int
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    23
  assumes "f (a - a + (a - a)) + f (   0    + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    24
  shows   "f (a - a + (a - a)) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    25
  by (rewrite in "f _ + f \<box> = _" diff_self) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    26
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    27
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    28
  fixes a b c :: int
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    29
  assumes "f (a - a +    0   ) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    30
  shows   "f (a - a + (a - a)) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    31
  by (rewrite at "f (_ + \<box>) + f _ = _" diff_self) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    32
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    33
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    34
  fixes a b c :: int
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    35
  assumes "f (  0   + (a - a)) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    36
  shows   "f (a - a + (a - a)) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    37
  by (rewrite in "f (\<box> + _) + _ = _" diff_self) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    38
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    39
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    40
  fixes a b c :: int
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    41
  assumes "f (a - a +    0   ) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    42
  shows   "f (a - a + (a - a)) + f ((a - a) + c) = f 0 + f c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    43
  by (rewrite in "f (_ + \<box>) + _ = _" diff_self) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    44
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    45
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    46
  fixes x y :: nat
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    47
  shows"x + y > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    48
  by (rewrite at "\<box> > c" add.commute) assumption
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    49
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    50
(* We can also rewrite in the assumptions.  *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    51
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    52
  fixes x y :: nat
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    53
  assumes "y + x > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    54
  shows   "x + y > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    55
  by (rewrite in asm add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    56
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    57
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    58
  fixes x y :: nat
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    59
  assumes "y + x > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    60
  shows   "x + y > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    61
  by (rewrite in "x + y > c" at asm add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    62
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    63
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    64
  fixes x y :: nat
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    65
  assumes "y + x > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    66
  shows   "x + y > c \<Longrightarrow> y + x > c"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    67
  by (rewrite at "\<box> > c" at asm  add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    68
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    69
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    70
  assumes "P {x::int. y + 1 = 1 + x}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    71
  shows   "P {x::int. y + 1 = x + 1}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    72
  by (rewrite at "x+1" in "{x::int. \<box> }" add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    73
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    74
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    75
  assumes "P {x::int. y + 1 = 1 + x}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    76
  shows   "P {x::int. y + 1 = x + 1}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    77
  by (rewrite at "any_identifier_will_work+1" in "{any_identifier_will_work::int. \<box> }" add.commute)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    78
   fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    79
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    80
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    81
  assumes "P {(x::nat, y::nat, z). x + z * 3 = Q (\<lambda>s t. s * t + y - 3)}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    82
  shows   "P {(x::nat, y::nat, z). x + z * 3 = Q (\<lambda>s t. y + s * t - 3)}"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    83
  by (rewrite at "b + d * e" in "\<lambda>(a, b, c). _ = Q (\<lambda>d e. \<box>)" add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    84
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    85
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    86
(* Rewriting with conditional rewriting rules works just as well. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    87
lemma test_theorem:
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    88
  fixes x :: nat
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    89
  shows "x \<le> y \<Longrightarrow> x \<ge> y \<Longrightarrow> x = y"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    90
  by (rule Orderings.order_antisym)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    91
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    92
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    93
fixes f :: "nat \<Rightarrow> nat"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    94
  assumes "f x \<le> 0" "f x \<ge> 0"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    95
  shows "f x = 0"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    96
  apply (rewrite at "f x" to "0" test_theorem)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    97
  apply fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    98
  apply fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
    99
  apply (rule refl)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   100
done
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   101
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   102
(*
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   103
   Instantiation.
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   104
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   105
   Since all rewriting is now done via conversions,
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   106
   instantiation becomes fairly easy to do.
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   107
*)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   108
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   109
(* We first introduce a function f and an extended
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   110
   version of f that is annotated with an invariant. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   111
fun f :: "nat \<Rightarrow> nat" where "f n = n"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   112
definition "f_inv (I :: nat \<Rightarrow> bool) n \<equiv> f n"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   113
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   114
lemma annotate_f: "f = f_inv I"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   115
  by (simp add: f_inv_def fun_eq_iff)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   116
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   117
(* We have a lemma with a bound variable n, and
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   118
   want to add an invariant to f. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   119
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   120
  assumes "P (\<lambda>n. f_inv (\<lambda>_. True) n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   121
  shows "P (\<lambda>n. f n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   122
  by (rewrite to "f_inv (\<lambda>_. True)" annotate_f) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   123
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   124
(* We can also add an invariant that contains the variable n bound in the outer context.
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   125
   For this, we need to bind this variable to an identifier. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   126
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   127
  assumes "P (\<lambda>n. f_inv (\<lambda>x. n < x + 1) n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   128
  shows "P (\<lambda>n. f n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   129
  by (rewrite in "\<lambda>n. \<box>" to "f_inv (\<lambda>x. n < x + 1)" annotate_f) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   130
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   131
(* Any identifier will work *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   132
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   133
  assumes "P (\<lambda>n. f_inv (\<lambda>x. n < x + 1) n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   134
  shows "P (\<lambda>n. f n + 1) = x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   135
  by (rewrite in "\<lambda>abc. \<box>" to "f_inv (\<lambda>x. abc < x + 1)" annotate_f) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   136
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   137
(* The "for" keyword. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   138
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   139
  assumes "P (2 + 1)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   140
  shows "\<And>x y. P (1 + 2 :: nat)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   141
by (rewrite in "P (1 + 2)" at for (x) add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   142
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   143
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   144
  assumes "\<And>x y. P (y + x)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   145
  shows "\<And>x y. P (x + y :: nat)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   146
by (rewrite in "P (x + _)" at for (x y) add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   147
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   148
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   149
  assumes "\<And>x y z. y + x + z = z + y + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   150
  shows   "\<And>x y z. x + y + z = z + y + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   151
by (rewrite at "x + y" in "x + y + z" in concl at for (x y z) add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   152
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   153
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   154
  assumes "\<And>x y z. z + (x + y) = z + y + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   155
  shows   "\<And>x y z. x + y + z = z + y + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   156
by (rewrite at "(_ + y) + z" in concl at for (y z) add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   157
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   158
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   159
  assumes "\<And>x y z. x + y + z = y + z + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   160
  shows   "\<And>x y z. x + y + z = z + y + (x::int)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   161
by (rewrite at "\<box> + _" at "_ = \<box>" in concl at for () add.commute) fact
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   162
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   163
(* The all-keyword can be used anywhere in the pattern where there is an \<And>-Quantifier. *)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   164
lemma
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   165
  assumes "(\<And>(x::int). x < 1 + x)"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   166
  and     "(x::int) + 1 > x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   167
  shows   "(\<And>(x::int). x + 1 > x) \<Longrightarrow> (x::int) + 1 > x"
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   168
by (rewrite at "x + 1" in for (x) at asm add.commute)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   169
   (rule assms)
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   170
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   171
end
4ed50ebf5d36 added proof method rewrite
noschinl
parents:
diff changeset
   172