src/HOL/ex/ReflectionEx.thy
changeset 28866 30cd9d89a0fb
parent 23650 0a6a719d24d5
child 29650 cc3958d31b1d
child 29667 53103fc8ffa3
equal deleted inserted replaced
28865:194e8f3439fe 28866:30cd9d89a0fb
     9 begin
     9 begin
    10 
    10 
    11 text{* This theory presents two methods: reify and reflection *}
    11 text{* This theory presents two methods: reify and reflection *}
    12 
    12 
    13 text{* 
    13 text{* 
    14 Consider an HOL type 'a, the structure of which is not recongnisable on the theory level. This is the case of bool, arithmetical terms such as int, real etc\<dots> 
    14 Consider an HOL type 'a, the structure of which is not recongnisable on the theory level. This is the case of bool, arithmetical terms such as int, real etc \dots
    15 In order to implement a simplification on terms of type 'a we often need its structure.
    15 In order to implement a simplification on terms of type 'a we often need its structure.
    16 Traditionnaly such simplifications are written in ML, proofs are synthesized.
    16 Traditionnaly such simplifications are written in ML, proofs are synthesized.
    17 An other strategy is to declare an HOL-datatype tau and an HOL function (the interpretation) that maps elements of tau to elements of 'a. The functionality of @{text reify} is to compute a term s::tau, which is the representant of t. For this it needs equations for the interpretation.
    17 An other strategy is to declare an HOL-datatype tau and an HOL function (the interpretation) that maps elements of tau to elements of 'a. The functionality of @{text reify} is to compute a term s::tau, which is the representant of t. For this it needs equations for the interpretation.
    18 
    18 
    19 NB: All the interpretations supported by @{text reify} must have the type @{text "'b list \<Rightarrow> tau \<Rightarrow> 'a"}.
    19 NB: All the interpretations supported by @{text reify} must have the type @{text "'b list \<Rightarrow> tau \<Rightarrow> 'a"}.
   129   Inum_Add: "Inum (Add s t) vs = Inum s vs + Inum t vs "
   129   Inum_Add: "Inum (Add s t) vs = Inum s vs + Inum t vs "
   130   Inum_Mul: "Inum (Mul c t) vs = c * Inum t vs "
   130   Inum_Mul: "Inum (Mul c t) vs = c * Inum t vs "
   131   Inum_CN : "Inum (CN n c t) vs = c*(vs!n) + Inum t vs "
   131   Inum_CN : "Inum (CN n c t) vs = c*(vs!n) + Inum t vs "
   132 
   132 
   133 
   133 
   134   text{* Let's reify some nat expressions \<dots> *}
   134   text{* Let's reify some nat expressions \dots *}
   135 lemma "4 * (2*x + (y::nat)) + f a \<noteq> 0"
   135 lemma "4 * (2*x + (y::nat)) + f a \<noteq> 0"
   136   apply (reify Inum.simps ("4 * (2*x + (y::nat)) + f a"))
   136   apply (reify Inum.simps ("4 * (2*x + (y::nat)) + f a"))
   137 oops
   137 oops
   138 text{* We're in a bad situation!! x, y and f a have been recongnized as a constants, which is correct but does not correspond to our intuition of the constructor C. It should encapsulate constants, i.e. numbers, i.e. numerals.*}
   138 text{* We're in a bad situation!! x, y and f a have been recongnized as a constants, which is correct but does not correspond to our intuition of the constructor C. It should encapsulate constants, i.e. numbers, i.e. numerals.*}
   139 
   139 
   140   text{* So let's leave the Inum_C equation at the end and see what happens \<dots>*}
   140   text{* So let's leave the @{text "Inum_C"} equation at the end and see what happens \dots*}
   141 lemma "4 * (2*x + (y::nat)) \<noteq> 0"
   141 lemma "4 * (2*x + (y::nat)) \<noteq> 0"
   142   apply (reify Inum_Var Inum_Add Inum_Mul Inum_CN Inum_C ("4 * (2*x + (y::nat))"))
   142   apply (reify Inum_Var Inum_Add Inum_Mul Inum_CN Inum_C ("4 * (2*x + (y::nat))"))
   143 oops
   143 oops
   144 text{* Hmmm let's specialize @{text Inum_C} with numerals.*}
   144 text{* Hmmm let's specialize @{text Inum_C} with numerals.*}
   145 
   145 
   148 
   148 
   149   text{* Second attempt *}
   149   text{* Second attempt *}
   150 lemma "1 * (2*x + (y::nat)) \<noteq> 0"
   150 lemma "1 * (2*x + (y::nat)) \<noteq> 0"
   151   apply (reify Inum_eqs ("1 * (2*x + (y::nat))"))
   151   apply (reify Inum_eqs ("1 * (2*x + (y::nat))"))
   152 oops
   152 oops
   153   text{* That was fine, so let's try an other one\<dots> *}
   153   text{* That was fine, so let's try another one \dots *}
   154 
   154 
   155 lemma "1 * (2* x + (y::nat) + 0 + 1) \<noteq> 0"
   155 lemma "1 * (2* x + (y::nat) + 0 + 1) \<noteq> 0"
   156   apply (reify Inum_eqs ("1 * (2*x + (y::nat) + 0 + 1)"))
   156   apply (reify Inum_eqs ("1 * (2*x + (y::nat) + 0 + 1)"))
   157 oops
   157 oops
   158   text{* Oh!! 0 is not a variable \<dots> Oh! 0 is not a number_of .. thing. The same for 1. So let's add those equations too *}
   158   text{* Oh!! 0 is not a variable \dots\ Oh! 0 is not a @{text "number_of"} \dots\ thing. The same for 1. So let's add those equations too *}
   159 
   159 
   160 lemma Inum_01: "Inum (C 0) vs = 0" "Inum (C 1) vs = 1" "Inum (C(Suc n)) vs = Suc n"
   160 lemma Inum_01: "Inum (C 0) vs = 0" "Inum (C 1) vs = 1" "Inum (C(Suc n)) vs = Suc n"
   161   by simp+
   161   by simp+
   162 
   162 
   163 lemmas Inum_eqs'= Inum_eqs Inum_01
   163 lemmas Inum_eqs'= Inum_eqs Inum_01
   225   "linaformsize (NEG p) = 2 + linaformsize p"
   225   "linaformsize (NEG p) = 2 + linaformsize p"
   226   "linaformsize (Conj p q) = 1 + linaformsize p + linaformsize q"
   226   "linaformsize (Conj p q) = 1 + linaformsize p + linaformsize q"
   227   "linaformsize (Disj p q) = 1 + linaformsize p + linaformsize q"
   227   "linaformsize (Disj p q) = 1 + linaformsize p + linaformsize q"
   228 
   228 
   229 
   229 
   230 consts aform :: "aform => nat list => bool"
   230 consts is_aform :: "aform => nat list => bool"
   231 primrec
   231 primrec
   232   "aform T vs = True"
   232   "is_aform T vs = True"
   233   "aform F vs = False"
   233   "is_aform F vs = False"
   234   "aform (Lt a b) vs = (Inum a vs < Inum b vs)"
   234   "is_aform (Lt a b) vs = (Inum a vs < Inum b vs)"
   235   "aform (Eq a b) vs = (Inum a vs = Inum b vs)"
   235   "is_aform (Eq a b) vs = (Inum a vs = Inum b vs)"
   236   "aform (Ge a b) vs = (Inum a vs \<ge> Inum b vs)"
   236   "is_aform (Ge a b) vs = (Inum a vs \<ge> Inum b vs)"
   237   "aform (NEq a b) vs = (Inum a vs \<noteq> Inum b vs)"
   237   "is_aform (NEq a b) vs = (Inum a vs \<noteq> Inum b vs)"
   238   "aform (NEG p) vs = (\<not> (aform p vs))"
   238   "is_aform (NEG p) vs = (\<not> (is_aform p vs))"
   239   "aform (Conj p q) vs = (aform p vs \<and> aform q vs)"
   239   "is_aform (Conj p q) vs = (is_aform p vs \<and> is_aform q vs)"
   240   "aform (Disj p q) vs = (aform p vs \<or> aform q vs)"
   240   "is_aform (Disj p q) vs = (is_aform p vs \<or> is_aform q vs)"
   241 
   241 
   242   text{* Let's reify and do reflection *}
   242   text{* Let's reify and do reflection *}
   243 lemma "(3::nat)*x + t < 0 \<and> (2 * x + y \<noteq> 17)"
   243 lemma "(3::nat)*x + t < 0 \<and> (2 * x + y \<noteq> 17)"
   244  apply (reify Inum_eqs' aform.simps) 
   244  apply (reify Inum_eqs' is_aform.simps) 
   245 oops
   245 oops
   246 
   246 
   247 text{* Note that reification handles several interpretations at the same time*}
   247 text{* Note that reification handles several interpretations at the same time*}
   248 lemma "(3::nat)*x + t < 0 & x*x + t*x + 3 + 1 = z*t*4*z | x + x + 1 < 0"
   248 lemma "(3::nat)*x + t < 0 & x*x + t*x + 3 + 1 = z*t*4*z | x + x + 1 < 0"
   249  apply (reflection Inum_eqs' aform.simps only:"x + x + 1") 
   249  apply (reflection Inum_eqs' is_aform.simps only:"x + x + 1") 
   250 oops
   250 oops
   251 
   251 
   252   text{* For reflection we now define a simple transformation on aform: NNF + linum on atoms *}
   252   text{* For reflection we now define a simple transformation on aform: NNF + linum on atoms *}
   253 consts linaform:: "aform \<Rightarrow> aform"
   253 consts linaform:: "aform \<Rightarrow> aform"
   254 recdef linaform "measure linaformsize"
   254 recdef linaform "measure linaformsize"
   267   "linaform (NEG (NEG p)) = linaform p"
   267   "linaform (NEG (NEG p)) = linaform p"
   268   "linaform (NEG (Conj p q)) = Disj (linaform (NEG p)) (linaform (NEG q))"
   268   "linaform (NEG (Conj p q)) = Disj (linaform (NEG p)) (linaform (NEG q))"
   269   "linaform (NEG (Disj p q)) = Conj (linaform (NEG p)) (linaform (NEG q))"
   269   "linaform (NEG (Disj p q)) = Conj (linaform (NEG p)) (linaform (NEG q))"
   270   "linaform p = p"
   270   "linaform p = p"
   271 
   271 
   272 lemma linaform: "aform (linaform p) vs = aform p vs"
   272 lemma linaform: "is_aform (linaform p) vs = is_aform p vs"
   273   by (induct p rule: linaform.induct, auto simp add: linum)
   273   by (induct p rule: linaform.induct) (auto simp add: linum)
   274 
   274 
   275 lemma "(((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0)))) + (Suc (Suc (Suc 0))) * ((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0))))< 0) \<and> (Suc 0  + Suc 0< 0)"
   275 lemma "(((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0)))) + (Suc (Suc (Suc 0))) * ((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0))))< 0) \<and> (Suc 0  + Suc 0< 0)"
   276    apply (reflection Inum_eqs' aform.simps rules: linaform)  
   276    apply (reflection Inum_eqs' is_aform.simps rules: linaform)  
   277 oops
   277 oops
   278 
   278 
   279 declare linaform[reflection]
   279 declare linaform[reflection]
   280 lemma "(((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0)))) + (Suc (Suc (Suc 0))) * ((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0))))< 0) \<and> (Suc 0  + Suc 0< 0)"
   280 lemma "(((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0)))) + (Suc (Suc (Suc 0))) * ((Suc(Suc (Suc 0)))*((x::nat) + (Suc (Suc 0))))< 0) \<and> (Suc 0  + Suc 0< 0)"
   281    apply (reflection Inum_eqs' aform.simps)
   281    apply (reflection Inum_eqs' is_aform.simps)
   282 oops
   282 oops
   283 
   283 
   284 text{* We now give an example where Interpretaions have 0 or more than only one envornement of different types and show that automatic reification also deals with binding *}
   284 text{* We now give an example where Interpretaions have 0 or more than only one envornement of different types and show that automatic reification also deals with binding *}
   285 datatype rb = BC bool| BAnd rb rb | BOr rb rb
   285 datatype rb = BC bool| BAnd rb rb | BOr rb rb
   286 consts Irb :: "rb \<Rightarrow> bool"
   286 consts Irb :: "rb \<Rightarrow> bool"
   331 datatype rnat = NC nat| NVar nat| NSuc rnat | NAdd rnat rnat | NMult rnat rnat | NNeg rnat | NSub rnat rnat | Nlgth rlist
   331 datatype rnat = NC nat| NVar nat| NSuc rnat | NAdd rnat rnat | NMult rnat rnat | NNeg rnat | NSub rnat rnat | Nlgth rlist
   332 consts Irnat :: "rnat \<Rightarrow> int list \<Rightarrow> (int list) list \<Rightarrow> nat list \<Rightarrow> nat"
   332 consts Irnat :: "rnat \<Rightarrow> int list \<Rightarrow> (int list) list \<Rightarrow> nat list \<Rightarrow> nat"
   333 primrec
   333 primrec
   334 Irnat_Suc: "Irnat (NSuc t) is ls vs = Suc (Irnat t is ls vs)"
   334 Irnat_Suc: "Irnat (NSuc t) is ls vs = Suc (Irnat t is ls vs)"
   335 Irnat_Var: "Irnat (NVar n) is ls vs = vs!n"
   335 Irnat_Var: "Irnat (NVar n) is ls vs = vs!n"
   336 Irnat_Neg: "Irnat (NNeg t) is ls vs = - Irnat t is ls vs"
   336 Irnat_Neg: "Irnat (NNeg t) is ls vs = 0"
   337 Irnat_Add: "Irnat (NAdd s t) is ls vs = Irnat s is ls vs + Irnat t is ls vs"
   337 Irnat_Add: "Irnat (NAdd s t) is ls vs = Irnat s is ls vs + Irnat t is ls vs"
   338 Irnat_Sub: "Irnat (NSub s t) is ls vs = Irnat s is ls vs - Irnat t is ls vs"
   338 Irnat_Sub: "Irnat (NSub s t) is ls vs = Irnat s is ls vs - Irnat t is ls vs"
   339 Irnat_Mult: "Irnat (NMult s t) is ls vs = Irnat s is ls vs * Irnat t is ls vs"
   339 Irnat_Mult: "Irnat (NMult s t) is ls vs = Irnat s is ls vs * Irnat t is ls vs"
   340 Irnat_lgth: "Irnat (Nlgth rxs) is ls vs = length (Irlist rxs is ls)"
   340 Irnat_lgth: "Irnat (Nlgth rxs) is ls vs = length (Irlist rxs is ls)"
   341 Irnat_C: "Irnat (NC i) is ls vs = i"
   341 Irnat_C: "Irnat (NC i) is ls vs = i"