src/HOL/Nominal/Examples/VC_Compatible.thy
author urbanc
Tue, 16 Oct 2007 13:00:13 +0200
changeset 25044 de1f50ab668d
parent 24897 b0a93a6d6ab9
child 25139 ffc5054a7274
permissions -rw-r--r--
polished some comments
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     1
(* $Id$ *)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     2
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     3
theory VC_Compatible
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     4
imports "../Nominal" 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     5
begin
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     6
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     7
text {* 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     8
  We show here two examples where using the variable  
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
     9
  convention carelessly in rule inductions, we end 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    10
  up with faulty lemmas. The point is that the examples
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    11
  are not variable-convention compatible and therefore
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    12
  in the nominal package one is protected from such
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    13
  bogus reasoning.
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    14
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    15
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    16
text {* 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    17
  We define alpha-equated lambda-terms as usual. 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    18
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    19
atom_decl name 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    20
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    21
nominal_datatype lam = 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    22
    Var "name"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    23
  | App "lam" "lam"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    24
  | Lam "\<guillemotleft>name\<guillemotright>lam" ("Lam [_]._" [100,100] 100)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    25
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    26
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    27
  The inductive relation 'unbind' unbinds the top-most  
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    28
  binders of a lambda-term; this relation is obviously  
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    29
  not a function, since it does not respect alpha-      
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    30
  equivalence. However as a relation unbind is ok and     
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    31
  a similar relation has been used in our formalisation 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    32
  of the algorithm W.
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    33
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    34
inductive
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    35
  unbind :: "lam \<Rightarrow> name list \<Rightarrow> lam \<Rightarrow> bool" ("_ \<mapsto> _,_" [60,60,60] 60)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    36
where
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    37
  u_var: "(Var a) \<mapsto> [],(Var a)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    38
| u_app: "(App t1 t2) \<mapsto> [],(App t1 t2)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    39
| u_lam: "t\<mapsto>xs,t' \<Longrightarrow> (Lam [x].t) \<mapsto> (x#xs),t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    40
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    41
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    42
  We can show that Lam [x]. Lam [x]. Var x unbinds to [x,x],Var x 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    43
  and also to [z,y],Var y (though the proof for the second is a 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    44
  bit clumsy).                                
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    45
*} 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    46
lemma unbind_lambda_lambda1: 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    47
  shows "Lam [x].Lam [x].(Var x)\<mapsto>[x,x],(Var x)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    48
by (auto intro: unbind.intros)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    49
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    50
lemma unbind_lambda_lambda2: 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    51
  shows "Lam [x].Lam [x].(Var x)\<mapsto>[y,z],(Var z)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    52
proof -
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    53
  have "Lam [x].Lam [x].(Var x) = Lam [y].Lam [z].(Var z)" 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    54
    by (auto simp add: lam.inject alpha calc_atm abs_fresh fresh_atm)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    55
  moreover
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    56
  have "Lam [y].Lam [z].(Var z) \<mapsto> [y,z],(Var z)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    57
    by (auto intro: unbind.intros)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    58
  ultimately 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    59
  show "Lam [x].Lam [x].(Var x)\<mapsto>[y,z],(Var z)" by simp
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    60
qed
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    61
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    62
text {* Unbind is equivariant ...*}
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    63
equivariance unbind
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    64
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    65
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    66
  ... but it is not variable-convention compatible (see Urban, 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    67
  Berghofer, Norrish [2007] for more details). This condition 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    68
  requires for rule u_lam, that the binder x is not a free variable 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    69
  in the rule's conclusion. Because this condition is not satisfied, 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    70
  Isabelle will not derive a strong induction principle for unbind 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    71
  - that means Isabelle does not allow you to use the variable 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    72
  convention in induction proofs involving unbind. We can, however,  
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    73
  force Isabelle to derive the strengthening induction principle. 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    74
*}
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    75
nominal_inductive unbind
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    76
  sorry
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    77
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    78
text {*
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    79
  To obtain our faulty lemma, we introduce the function 'bind'
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    80
  which takes a list of names and abstracts away these names in 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    81
  a given lambda-term.                                     
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    82
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    83
fun 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    84
  bind :: "name list \<Rightarrow> lam \<Rightarrow> lam"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    85
where
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    86
  "bind [] t = t"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    87
| "bind (x#xs) t = Lam [x].(bind xs t)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    88
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    89
text {*
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    90
  Although not necessary for our main argument below, we can 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    91
  easily prove that bind undoes the unbinding.               
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    92
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    93
lemma bind_unbind:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    94
  assumes a: "t \<mapsto> xs,t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    95
  shows "t = bind xs t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    96
using a by (induct) (auto)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    97
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
    98
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
    99
  The next lemma shows by induction on xs that if x is a free 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   100
  variable in t and x does not occur in xs, then x is a free 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   101
  variable in bind xs t. In the nominal tradition we formulate    
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   102
  'is a free variable in' as 'is not fresh for'.         
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   103
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   104
lemma free_variable:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   105
  fixes x::"name"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   106
  assumes a: "\<not>(x\<sharp>t)" and b: "x\<sharp>xs"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   107
  shows "\<not>(x\<sharp>bind xs t)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   108
using a b
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   109
by (induct xs)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   110
   (auto simp add: fresh_list_cons abs_fresh fresh_atm)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   111
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   112
text {*
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   113
  Now comes the faulty lemma. It is derived using the     
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   114
  variable convention, that means using the strong induction 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   115
  principle we 'proved' above by using sorry. This faulty    
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   116
  lemma states that if t unbinds to x::xs and t', and x is a 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   117
  free variable in t', then it is also a free variable in    
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   118
  bind xs t'. We show this lemma by assuming that the binder 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   119
  x is fresh w.r.t. to the xs unbound previously.            
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   120
*}   
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   121
lemma faulty1:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   122
  assumes a: "t\<mapsto>(x#xs),t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   123
  shows "\<not>(x\<sharp>t') \<Longrightarrow> \<not>(x\<sharp>bind xs t')"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   124
using a
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   125
by (nominal_induct t xs'\<equiv>"x#xs" t' avoiding: xs rule: unbind.strong_induct)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   126
   (simp_all add: free_variable)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   127
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   128
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   129
  Obviously the faulty lemma does not hold, for example, in 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   130
  case Lam [x].Lam [x].(Var x) \<mapsto> [x,x],(Var x). Therefore,
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   131
  we can prove False.             
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   132
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   133
lemma false1:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   134
  shows "False"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   135
proof -
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   136
  have "Lam [x].Lam [x].(Var x)\<mapsto>[x,x],(Var x)" 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   137
  and  "\<not>(x\<sharp>Var x)" by (simp_all add: unbind_lambda_lambda1 fresh_atm)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   138
  then have "\<not>(x\<sharp>(bind [x] (Var x)))" by (rule faulty1)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   139
  moreover 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   140
  have "x\<sharp>(bind [x] (Var x))" by (simp add: abs_fresh)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   141
  ultimately
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   142
  show "False" by simp
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   143
qed
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   144
   
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   145
text {* 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   146
  The next example is slightly simpler, but looks more
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   147
  contrived than 'unbind'. This example, caled 'strip' just 
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   148
  strips off the top-most binders from lambdas. 
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   149
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   150
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   151
inductive
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   152
  strip :: "lam \<Rightarrow> lam \<Rightarrow> bool" ("_ \<rightarrow> _" [60,60] 60)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   153
where
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   154
  s_var: "(Var a) \<rightarrow> (Var a)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   155
| s_app: "(App t1 t2) \<rightarrow> (App t1 t2)"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   156
| s_lam: "t \<rightarrow> t' \<Longrightarrow> (Lam [x].t) \<rightarrow> t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   157
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   158
text {* 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   159
  The relation is equivariant but we have to use again 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   160
  sorry to derive a strong induction principle.
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   161
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   162
equivariance strip
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   163
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   164
nominal_inductive strip
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   165
  sorry
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   166
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   167
text {*
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   168
  The faulty lemma shows that a variable that is fresh
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   169
  for a term is also fresh for the term after striping.
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   170
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   171
lemma faulty2:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   172
  fixes x::"name"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   173
  assumes a: "t \<rightarrow> t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   174
  shows "x\<sharp>t \<Longrightarrow> x\<sharp>t'"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   175
using a
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   176
by (nominal_induct t t'\<equiv>t' avoiding: t' rule: strip.strong_induct)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   177
   (auto simp add: abs_fresh)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   178
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   179
text {*
25044
de1f50ab668d polished some comments
urbanc
parents: 24897
diff changeset
   180
  Obviously Lam [x].Var x is a counter example to this lemma.
24897
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   181
*}
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   182
lemma false2:
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   183
  shows "False"
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   184
proof -
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   185
  have "Lam [x].(Var x) \<rightarrow> (Var x)" by (auto intro: strip.intros)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   186
  moreover
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   187
  have "x\<sharp>Lam [x].(Var x)" by (simp add: abs_fresh)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   188
  ultimately have "x\<sharp>(Var x)" by (simp only: faulty2)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   189
  then show "False" by (simp add: fresh_atm)
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   190
qed 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   191
 
b0a93a6d6ab9 changed file name
urbanc
parents:
diff changeset
   192
end