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