1 (* Title: HOL/ex/Reflection_Examples.thy |
1 (* Title: HOL/ex/Reflection_Examples.thy |
2 Author: Amine Chaieb, TU Muenchen |
2 Author: Amine Chaieb, TU Muenchen |
3 *) |
3 *) |
4 |
4 |
5 section {* Examples for generic reflection and reification *} |
5 section \<open>Examples for generic reflection and reification\<close> |
6 |
6 |
7 theory Reflection_Examples |
7 theory Reflection_Examples |
8 imports Complex_Main "~~/src/HOL/Library/Reflection" |
8 imports Complex_Main "~~/src/HOL/Library/Reflection" |
9 begin |
9 begin |
10 |
10 |
11 text {* This theory presents two methods: reify and reflection *} |
11 text \<open>This theory presents two methods: reify and reflection\<close> |
12 |
12 |
13 text {* |
13 text \<open> |
14 Consider an HOL type @{text \<sigma>}, the structure of which is not recongnisable |
14 Consider an HOL type @{text \<sigma>}, the structure of which is not recongnisable |
15 on the theory level. This is the case of @{typ bool}, arithmetical terms such as @{typ int}, |
15 on the theory level. This is the case of @{typ bool}, arithmetical terms such as @{typ int}, |
16 @{typ real} etc \dots In order to implement a simplification on terms of type @{text \<sigma>} we |
16 @{typ real} etc \dots In order to implement a simplification on terms of type @{text \<sigma>} we |
17 often need its structure. Traditionnaly such simplifications are written in ML, |
17 often need its structure. Traditionnaly such simplifications are written in ML, |
18 proofs are synthesized. |
18 proofs are synthesized. |
113 | "nnf (NOT (Imp p q)) = And (nnf p) (nnf (NOT q))" |
113 | "nnf (NOT (Imp p q)) = And (nnf p) (nnf (NOT q))" |
114 | "nnf (NOT (Iff p q)) = Or (And (nnf p) (nnf (NOT q))) (And (nnf (NOT p)) (nnf q))" |
114 | "nnf (NOT (Iff p q)) = Or (And (nnf p) (nnf (NOT q))) (And (nnf (NOT p)) (nnf q))" |
115 | "nnf (NOT (NOT p)) = nnf p" |
115 | "nnf (NOT (NOT p)) = nnf p" |
116 | "nnf (NOT p) = NOT p" |
116 | "nnf (NOT p) = NOT p" |
117 |
117 |
118 text {* The correctness theorem of @{const nnf}: it preserves the semantics of @{typ fm} *} |
118 text \<open>The correctness theorem of @{const nnf}: it preserves the semantics of @{typ fm}\<close> |
119 lemma nnf [reflection]: |
119 lemma nnf [reflection]: |
120 "Ifm (nnf p) vs = Ifm p vs" |
120 "Ifm (nnf p) vs = Ifm p vs" |
121 by (induct p rule: nnf.induct) auto |
121 by (induct p rule: nnf.induct) auto |
122 |
122 |
123 text {* Now let's perform NNF using our @{const nnf} function defined above. First to the |
123 text \<open>Now let's perform NNF using our @{const nnf} function defined above. First to the |
124 whole subgoal. *} |
124 whole subgoal.\<close> |
125 lemma "A \<noteq> B \<and> (B \<longrightarrow> A \<noteq> (B \<or> C \<and> (B \<longrightarrow> A \<or> D))) \<longrightarrow> A \<or> B \<and> D" |
125 lemma "A \<noteq> B \<and> (B \<longrightarrow> A \<noteq> (B \<or> C \<and> (B \<longrightarrow> A \<or> D))) \<longrightarrow> A \<or> B \<and> D" |
126 apply (reflection Ifm.simps) |
126 apply (reflection Ifm.simps) |
127 oops |
127 oops |
128 |
128 |
129 text {* Now we specify on which subterm it should be applied *} |
129 text \<open>Now we specify on which subterm it should be applied\<close> |
130 lemma "A \<noteq> B \<and> (B \<longrightarrow> A \<noteq> (B \<or> C \<and> (B \<longrightarrow> A \<or> D))) \<longrightarrow> A \<or> B \<and> D" |
130 lemma "A \<noteq> B \<and> (B \<longrightarrow> A \<noteq> (B \<or> C \<and> (B \<longrightarrow> A \<or> D))) \<longrightarrow> A \<or> B \<and> D" |
131 apply (reflection Ifm.simps only: "B \<or> C \<and> (B \<longrightarrow> A \<or> D)") |
131 apply (reflection Ifm.simps only: "B \<or> C \<and> (B \<longrightarrow> A \<or> D)") |
132 oops |
132 oops |
133 |
133 |
134 |
134 |
135 text {* Example 2: Simple arithmetic formulae *} |
135 text \<open>Example 2: Simple arithmetic formulae\<close> |
136 |
136 |
137 text {* The type @{text num} reflects linear expressions over natural number *} |
137 text \<open>The type @{text num} reflects linear expressions over natural number\<close> |
138 datatype num = C nat | Add num num | Mul nat num | Var nat | CN nat nat num |
138 datatype num = C nat | Add num num | Mul nat num | Var nat | CN nat nat num |
139 |
139 |
140 text {* This is just technical to make recursive definitions easier. *} |
140 text \<open>This is just technical to make recursive definitions easier.\<close> |
141 primrec num_size :: "num \<Rightarrow> nat" |
141 primrec num_size :: "num \<Rightarrow> nat" |
142 where |
142 where |
143 "num_size (C c) = 1" |
143 "num_size (C c) = 1" |
144 | "num_size (Var n) = 1" |
144 | "num_size (Var n) = 1" |
145 | "num_size (Add a b) = 1 + num_size a + num_size b" |
145 | "num_size (Add a b) = 1 + num_size a + num_size b" |
146 | "num_size (Mul c a) = 1 + num_size a" |
146 | "num_size (Mul c a) = 1 + num_size a" |
147 | "num_size (CN n c a) = 4 + num_size a " |
147 | "num_size (CN n c a) = 4 + num_size a " |
148 |
148 |
149 lemma [measure_function]: "is_measure num_size" .. |
149 lemma [measure_function]: "is_measure num_size" .. |
150 |
150 |
151 text {* The semantics of num *} |
151 text \<open>The semantics of num\<close> |
152 primrec Inum:: "num \<Rightarrow> nat list \<Rightarrow> nat" |
152 primrec Inum:: "num \<Rightarrow> nat list \<Rightarrow> nat" |
153 where |
153 where |
154 Inum_C : "Inum (C i) vs = i" |
154 Inum_C : "Inum (C i) vs = i" |
155 | Inum_Var: "Inum (Var n) vs = vs!n" |
155 | Inum_Var: "Inum (Var n) vs = vs!n" |
156 | Inum_Add: "Inum (Add s t) vs = Inum s vs + Inum t vs " |
156 | Inum_Add: "Inum (Add s t) vs = Inum s vs + Inum t vs " |
157 | Inum_Mul: "Inum (Mul c t) vs = c * Inum t vs " |
157 | Inum_Mul: "Inum (Mul c t) vs = c * Inum t vs " |
158 | Inum_CN : "Inum (CN n c t) vs = c*(vs!n) + Inum t vs " |
158 | Inum_CN : "Inum (CN n c t) vs = c*(vs!n) + Inum t vs " |
159 |
159 |
160 text {* Let's reify some nat expressions \dots *} |
160 text \<open>Let's reify some nat expressions \dots\<close> |
161 lemma "4 * (2 * x + (y::nat)) + f a \<noteq> 0" |
161 lemma "4 * (2 * x + (y::nat)) + f a \<noteq> 0" |
162 apply (reify Inum.simps ("4 * (2 * x + (y::nat)) + f a")) |
162 apply (reify Inum.simps ("4 * (2 * x + (y::nat)) + f a")) |
163 oops |
163 oops |
164 text {* We're in a bad situation! @{text x}, @{text y} and @{text f} have been recongnized |
164 text \<open>We're in a bad situation! @{text x}, @{text y} and @{text f} have been recongnized |
165 as constants, which is correct but does not correspond to our intuition of the constructor C. |
165 as constants, which is correct but does not correspond to our intuition of the constructor C. |
166 It should encapsulate constants, i.e. numbers, i.e. numerals. *} |
166 It should encapsulate constants, i.e. numbers, i.e. numerals.\<close> |
167 |
167 |
168 text {* So let's leave the @{text "Inum_C"} equation at the end and see what happens \dots*} |
168 text \<open>So let's leave the @{text "Inum_C"} equation at the end and see what happens \dots\<close> |
169 lemma "4 * (2 * x + (y::nat)) \<noteq> 0" |
169 lemma "4 * (2 * x + (y::nat)) \<noteq> 0" |
170 apply (reify Inum_Var Inum_Add Inum_Mul Inum_CN Inum_C ("4 * (2 * x + (y::nat))")) |
170 apply (reify Inum_Var Inum_Add Inum_Mul Inum_CN Inum_C ("4 * (2 * x + (y::nat))")) |
171 oops |
171 oops |
172 text {* Hm, let's specialize @{text Inum_C} with numerals.*} |
172 text \<open>Hm, let's specialize @{text Inum_C} with numerals.\<close> |
173 |
173 |
174 lemma Inum_number: "Inum (C (numeral t)) vs = numeral t" by simp |
174 lemma Inum_number: "Inum (C (numeral t)) vs = numeral t" by simp |
175 lemmas Inum_eqs = Inum_Var Inum_Add Inum_Mul Inum_CN Inum_number |
175 lemmas Inum_eqs = Inum_Var Inum_Add Inum_Mul Inum_CN Inum_number |
176 |
176 |
177 text {* Second attempt *} |
177 text \<open>Second attempt\<close> |
178 lemma "1 * (2 * x + (y::nat)) \<noteq> 0" |
178 lemma "1 * (2 * x + (y::nat)) \<noteq> 0" |
179 apply (reify Inum_eqs ("1 * (2 * x + (y::nat))")) |
179 apply (reify Inum_eqs ("1 * (2 * x + (y::nat))")) |
180 oops |
180 oops |
181 |
181 |
182 text{* That was fine, so let's try another one \dots *} |
182 text\<open>That was fine, so let's try another one \dots\<close> |
183 |
183 |
184 lemma "1 * (2 * x + (y::nat) + 0 + 1) \<noteq> 0" |
184 lemma "1 * (2 * x + (y::nat) + 0 + 1) \<noteq> 0" |
185 apply (reify Inum_eqs ("1 * (2 * x + (y::nat) + 0 + 1)")) |
185 apply (reify Inum_eqs ("1 * (2 * x + (y::nat) + 0 + 1)")) |
186 oops |
186 oops |
187 |
187 |
188 text {* Oh!! 0 is not a variable \dots\ Oh! 0 is not a @{text "numeral"} \dots\ thing. |
188 text \<open>Oh!! 0 is not a variable \dots\ Oh! 0 is not a @{text "numeral"} \dots\ thing. |
189 The same for 1. So let's add those equations, too. *} |
189 The same for 1. So let's add those equations, too.\<close> |
190 |
190 |
191 lemma Inum_01: "Inum (C 0) vs = 0" "Inum (C 1) vs = 1" "Inum (C(Suc n)) vs = Suc n" |
191 lemma Inum_01: "Inum (C 0) vs = 0" "Inum (C 1) vs = 1" "Inum (C(Suc n)) vs = Suc n" |
192 by simp_all |
192 by simp_all |
193 |
193 |
194 lemmas Inum_eqs'= Inum_eqs Inum_01 |
194 lemmas Inum_eqs'= Inum_eqs Inum_01 |
195 |
195 |
196 text{* Third attempt: *} |
196 text\<open>Third attempt:\<close> |
197 |
197 |
198 lemma "1 * (2 * x + (y::nat) + 0 + 1) \<noteq> 0" |
198 lemma "1 * (2 * x + (y::nat) + 0 + 1) \<noteq> 0" |
199 apply (reify Inum_eqs' ("1 * (2 * x + (y::nat) + 0 + 1)")) |
199 apply (reify Inum_eqs' ("1 * (2 * x + (y::nat) + 0 + 1)")) |
200 oops |
200 oops |
201 |
201 |
202 text {* Okay, let's try reflection. Some simplifications on @{typ num} follow. You can |
202 text \<open>Okay, let's try reflection. Some simplifications on @{typ num} follow. You can |
203 skim until the main theorem @{text linum}. *} |
203 skim until the main theorem @{text linum}.\<close> |
204 |
204 |
205 fun lin_add :: "num \<Rightarrow> num \<Rightarrow> num" |
205 fun lin_add :: "num \<Rightarrow> num \<Rightarrow> num" |
206 where |
206 where |
207 "lin_add (CN n1 c1 r1) (CN n2 c2 r2) = |
207 "lin_add (CN n1 c1 r1) (CN n2 c2 r2) = |
208 (if n1 = n2 then |
208 (if n1 = n2 then |
279 | "is_aform (NEq a b) vs = (Inum a vs \<noteq> Inum b vs)" |
279 | "is_aform (NEq a b) vs = (Inum a vs \<noteq> Inum b vs)" |
280 | "is_aform (NEG p) vs = (\<not> (is_aform p vs))" |
280 | "is_aform (NEG p) vs = (\<not> (is_aform p vs))" |
281 | "is_aform (Conj p q) vs = (is_aform p vs \<and> is_aform q vs)" |
281 | "is_aform (Conj p q) vs = (is_aform p vs \<and> is_aform q vs)" |
282 | "is_aform (Disj p q) vs = (is_aform p vs \<or> is_aform q vs)" |
282 | "is_aform (Disj p q) vs = (is_aform p vs \<or> is_aform q vs)" |
283 |
283 |
284 text{* Let's reify and do reflection *} |
284 text\<open>Let's reify and do reflection\<close> |
285 lemma "(3::nat) * x + t < 0 \<and> (2 * x + y \<noteq> 17)" |
285 lemma "(3::nat) * x + t < 0 \<and> (2 * x + y \<noteq> 17)" |
286 apply (reify Inum_eqs' is_aform.simps) |
286 apply (reify Inum_eqs' is_aform.simps) |
287 oops |
287 oops |
288 |
288 |
289 text {* Note that reification handles several interpretations at the same time*} |
289 text \<open>Note that reification handles several interpretations at the same time\<close> |
290 lemma "(3::nat) * x + t < 0 \<and> x * x + t * x + 3 + 1 = z * t * 4 * z \<or> x + x + 1 < 0" |
290 lemma "(3::nat) * x + t < 0 \<and> x * x + t * x + 3 + 1 = z * t * 4 * z \<or> x + x + 1 < 0" |
291 apply (reflection Inum_eqs' is_aform.simps only: "x + x + 1") |
291 apply (reflection Inum_eqs' is_aform.simps only: "x + x + 1") |
292 oops |
292 oops |
293 |
293 |
294 text {* For reflection we now define a simple transformation on aform: NNF + linum on atoms *} |
294 text \<open>For reflection we now define a simple transformation on aform: NNF + linum on atoms\<close> |
295 |
295 |
296 fun linaform:: "aform \<Rightarrow> aform" |
296 fun linaform:: "aform \<Rightarrow> aform" |
297 where |
297 where |
298 "linaform (Lt s t) = Lt (linum s) (linum t)" |
298 "linaform (Lt s t) = Lt (linum s) (linum t)" |
299 | "linaform (Eq s t) = Eq (linum s) (linum t)" |
299 | "linaform (Eq s t) = Eq (linum s) (linum t)" |