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" |