1 theory FSet3 |
1 theory FSet3 |
2 imports "../QuotMain" List |
2 imports "../QuotMain" "../QuotList" List |
3 begin |
3 begin |
4 |
4 |
5 fun |
5 fun |
6 list_eq :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" (infix "\<approx>" 50) |
6 list_eq :: "'a list \<Rightarrow> 'a list \<Rightarrow> bool" (infix "\<approx>" 50) |
7 where |
7 where |
8 "list_eq xs ys = (\<forall>e. (e \<in> set xs) = (e \<in> set ys))" |
8 "list_eq xs ys = (\<forall>x. x \<in> set xs \<longleftrightarrow> x \<in> set ys)" |
9 |
9 |
10 lemma list_eq_equivp: |
10 lemma list_eq_equivp: |
11 shows "equivp list_eq" |
11 shows "equivp list_eq" |
12 unfolding equivp_reflp_symp_transp reflp_def symp_def transp_def |
12 unfolding equivp_reflp_symp_transp reflp_def symp_def transp_def |
13 by auto |
13 by auto |
14 |
14 |
15 quotient_type fset = "'a list" / "list_eq" |
15 quotient_type |
16 by (rule list_eq_equivp) |
16 fset = "'a list" / "list_eq" |
17 |
17 by (rule list_eq_equivp) |
18 lemma not_nil_equiv_cons: |
18 |
19 "\<not>[] \<approx> a # A" |
19 |
20 by auto |
20 section {* empty fset, finsert and membership *} |
|
21 |
|
22 quotient_definition |
|
23 "fempty :: 'a fset" ("{||}") |
|
24 as "[]::'a list" |
|
25 |
|
26 quotient_definition |
|
27 "finsert :: 'a \<Rightarrow> 'a fset \<Rightarrow> 'a fset" |
|
28 as "op #" |
|
29 |
|
30 syntax |
|
31 "@Finset" :: "args => 'a fset" ("{|(_)|}") |
|
32 |
|
33 translations |
|
34 "{|x, xs|}" == "CONST finsert x {|xs|}" |
|
35 "{|x|}" == "CONST finsert x {||}" |
|
36 |
|
37 definition |
|
38 memb :: "'a \<Rightarrow> 'a list \<Rightarrow> bool" |
|
39 where |
|
40 "memb x xs \<equiv> x \<in> set xs" |
|
41 |
|
42 quotient_definition |
|
43 "fin :: 'a \<Rightarrow> 'a fset \<Rightarrow> bool" ("_ |\<in>| _" [50, 51] 50) |
|
44 as "memb" |
|
45 |
|
46 abbreviation |
|
47 fnotin :: "'a \<Rightarrow> 'a fset \<Rightarrow> bool" ("_ |\<notin>| _" [50, 51] 50) |
|
48 where |
|
49 "a |\<notin>| S \<equiv> \<not>(a |\<in>| S)" |
|
50 |
|
51 lemma memb_rsp[quot_respect]: |
|
52 shows "(op = ===> op \<approx> ===> op =) memb memb" |
|
53 by (auto simp add: memb_def) |
21 |
54 |
22 lemma nil_rsp[quot_respect]: |
55 lemma nil_rsp[quot_respect]: |
23 shows "[] \<approx> []" |
56 shows "[] \<approx> []" |
24 by simp |
57 by simp |
25 |
58 |
26 lemma cons_rsp[quot_respect]: |
59 lemma cons_rsp[quot_respect]: |
27 shows "(op = ===> op \<approx> ===> op \<approx>) op # op #" |
60 shows "(op = ===> op \<approx> ===> op \<approx>) op # op #" |
28 by simp |
61 by simp |
29 |
62 |
30 (* |
63 |
31 lemma mem_rsp[quot_respect]: |
64 section {* Augmenting a set -- @{const finsert} *} |
32 "(op = ===> op \<approx> ===> op =) (op mem) (op mem)" |
65 |
|
66 text {* raw section *} |
|
67 |
|
68 lemma nil_not_cons: |
|
69 shows "\<not>[] \<approx> x # xs" |
|
70 by auto |
|
71 |
|
72 lemma memb_cons_iff: |
|
73 shows "memb x (y # xs) = (x = y \<or> memb x xs)" |
|
74 by (induct xs) (auto simp add: memb_def) |
|
75 |
|
76 lemma memb_consI1: |
|
77 shows "memb x (x # xs)" |
|
78 by (simp add: memb_def) |
|
79 |
|
80 lemma memb_consI2: |
|
81 shows "memb x xs \<Longrightarrow> memb x (y # xs)" |
|
82 by (simp add: memb_def) |
|
83 |
|
84 lemma memb_absorb: |
|
85 shows "memb x xs \<Longrightarrow> (x # xs) \<approx> xs" |
|
86 by (induct xs) (auto simp add: memb_def) |
|
87 |
|
88 text {* lifted section *} |
|
89 |
|
90 lemma fempty_not_finsert[simp]: |
|
91 shows "{||} \<noteq> finsert x S" |
|
92 by (lifting nil_not_cons) |
|
93 |
|
94 lemma fin_finsert_iff[simp]: |
|
95 "x |\<in>| finsert y S = (x = y \<or> x |\<in>| S)" |
|
96 by (lifting memb_cons_iff) |
|
97 |
|
98 lemma |
|
99 shows finsertI1: "x |\<in>| finsert x S" |
|
100 and finsertI2: "x |\<in>| S \<Longrightarrow> x |\<in>| finsert y S" |
|
101 by (lifting memb_consI1, lifting memb_consI2) |
|
102 |
|
103 lemma finsert_absorb [simp]: |
|
104 shows "x |\<in>| S \<Longrightarrow> finsert x S = S" |
|
105 by (lifting memb_absorb) |
|
106 |
|
107 |
|
108 section {* Singletons *} |
|
109 |
|
110 text {* raw section *} |
|
111 |
|
112 lemma singleton_list_eq: |
|
113 shows "[x] \<approx> [y] \<longleftrightarrow> x = y" |
|
114 by auto |
|
115 |
|
116 text {* lifted section *} |
|
117 |
|
118 lemma fsingleton_eq[simp]: |
|
119 shows "{|x|} = {|y|} \<longleftrightarrow> x = y" |
|
120 by (lifting singleton_list_eq) |
|
121 |
|
122 |
|
123 section {* Cardinality of finite sets *} |
|
124 |
|
125 fun |
|
126 fcard_raw :: "'a list \<Rightarrow> nat" |
|
127 where |
|
128 fcard_raw_nil: "fcard_raw [] = 0" |
|
129 | fcard_raw_cons: "fcard_raw (x # xs) = (if memb x xs then fcard_raw xs else Suc (fcard_raw xs))" |
|
130 |
|
131 quotient_definition |
|
132 "fcard :: 'a fset \<Rightarrow> nat" |
|
133 as "fcard_raw" |
|
134 |
|
135 text {* raw section *} |
|
136 |
|
137 lemma fcard_raw_ge_0: |
|
138 assumes a: "x \<in> set xs" |
|
139 shows "0 < fcard_raw xs" |
|
140 using a |
|
141 by (induct xs) (auto simp add: memb_def) |
|
142 |
|
143 lemma fcard_raw_delete_one: |
|
144 "fcard_raw ([x \<leftarrow> xs. x \<noteq> y]) = (if memb y xs then fcard_raw xs - 1 else fcard_raw xs)" |
|
145 by (induct xs) (auto dest: fcard_raw_ge_0 simp add: memb_def) |
|
146 |
|
147 lemma fcard_raw_rsp_aux: |
|
148 assumes a: "a \<approx> b" |
|
149 shows "fcard_raw a = fcard_raw b" |
|
150 using a |
|
151 apply(induct a arbitrary: b) |
|
152 apply(auto simp add: memb_def) |
|
153 apply(metis) |
|
154 apply(drule_tac x="[x \<leftarrow> b. x \<noteq> a1]" in meta_spec) |
|
155 apply(simp add: fcard_raw_delete_one) |
|
156 apply(metis Suc_pred' fcard_raw_ge_0 fcard_raw_delete_one memb_def) |
|
157 done |
|
158 |
|
159 lemma fcard_raw_rsp[quot_respect]: |
|
160 "(op \<approx> ===> op =) fcard_raw fcard_raw" |
|
161 by (simp add: fcard_raw_rsp_aux) |
|
162 |
|
163 text {* lifted section *} |
|
164 |
|
165 lemma fcard_fempty [simp]: |
|
166 shows "fcard {||} = 0" |
|
167 by (lifting fcard_raw_nil) |
|
168 |
|
169 lemma fcard_finsert_if [simp]: |
|
170 shows "fcard (finsert x S) = (if x |\<in>| S then fcard S else Suc (fcard S))" |
|
171 by (lifting fcard_raw_cons) |
|
172 |
|
173 |
|
174 section {* Induction and Cases rules for finite sets *} |
|
175 |
|
176 lemma fset_exhaust[case_names fempty finsert, cases type: fset]: |
|
177 shows "\<lbrakk>S = {||} \<Longrightarrow> P; \<And>x S'. S = finsert x S' \<Longrightarrow> P\<rbrakk> \<Longrightarrow> P" |
|
178 by (lifting list.exhaust) |
|
179 |
|
180 lemma fset_induct[case_names fempty finsert]: |
|
181 shows "\<lbrakk>P {||}; \<And>x S. P S \<Longrightarrow> P (finsert x S)\<rbrakk> \<Longrightarrow> P S" |
|
182 by (lifting list.induct) |
|
183 |
|
184 lemma fset_induct2[case_names fempty finsert, induct type: fset]: |
|
185 assumes prem1: "P {||}" |
|
186 and prem2: "\<And>x S. \<lbrakk>x |\<notin>| S; P S\<rbrakk> \<Longrightarrow> P (finsert x S)" |
|
187 shows "P S" |
|
188 proof(induct S rule: fset_induct) |
|
189 case fempty |
|
190 show "P {||}" by (rule prem1) |
|
191 next |
|
192 case (finsert x S) |
|
193 have asm: "P S" by fact |
|
194 show "P (finsert x S)" |
|
195 proof(cases "x |\<in>| S") |
|
196 case True |
|
197 have "x |\<in>| S" by fact |
|
198 then show "P (finsert x S)" using asm by simp |
|
199 next |
|
200 case False |
|
201 have "x |\<notin>| S" by fact |
|
202 then show "P (finsert x S)" using prem2 asm by simp |
|
203 qed |
|
204 qed |
|
205 |
|
206 |
|
207 section {* fmap and fset comprehension *} |
|
208 |
|
209 quotient_definition |
|
210 "fmap :: ('a \<Rightarrow> 'b) \<Rightarrow> 'a fset \<Rightarrow> 'b fset" |
|
211 as |
|
212 "map" |
|
213 |
|
214 (* PROPBLEM |
|
215 quotient_definition |
|
216 "fconcat :: ('a fset) fset => 'a fset" |
|
217 as |
|
218 "concat" |
|
219 |
|
220 term concat |
|
221 term fconcat |
33 *) |
222 *) |
|
223 |
|
224 consts |
|
225 fconcat :: "('a fset) fset => 'a fset" |
|
226 |
|
227 text {* raw section *} |
|
228 |
|
229 lemma map_rsp_aux: |
|
230 assumes a: "a \<approx> b" |
|
231 shows "map f a \<approx> map f b" |
|
232 using a |
|
233 apply(induct a arbitrary: b) |
|
234 apply(auto) |
|
235 apply(metis rev_image_eqI) |
|
236 done |
|
237 |
|
238 lemma map_rsp[quot_respect]: |
|
239 shows "(op = ===> op \<approx> ===> op \<approx>) map map" |
|
240 by (auto simp add: map_rsp_aux) |
|
241 |
|
242 |
|
243 text {* lifted section *} |
|
244 |
|
245 (* TBD *) |
|
246 |
|
247 text {* syntax for fset comprehensions (adapted from lists) *} |
|
248 |
|
249 nonterminals fsc_qual fsc_quals |
|
250 |
|
251 syntax |
|
252 "_fsetcompr" :: "'a \<Rightarrow> fsc_qual \<Rightarrow> fsc_quals \<Rightarrow> 'a fset" ("{|_ . __") |
|
253 "_fsc_gen" :: "'a \<Rightarrow> 'a fset \<Rightarrow> fsc_qual" ("_ <- _") |
|
254 "_fsc_test" :: "bool \<Rightarrow> fsc_qual" ("_") |
|
255 "_fsc_end" :: "fsc_quals" ("|}") |
|
256 "_fsc_quals" :: "fsc_qual \<Rightarrow> fsc_quals \<Rightarrow> fsc_quals" (", __") |
|
257 "_fsc_abs" :: "'a => 'b fset => 'b fset" |
|
258 |
|
259 syntax (xsymbols) |
|
260 "_fsc_gen" :: "'a \<Rightarrow> 'a fset \<Rightarrow> fsc_qual" ("_ \<leftarrow> _") |
|
261 syntax (HTML output) |
|
262 "_fsc_gen" :: "'a \<Rightarrow> 'a fset \<Rightarrow> fsc_qual" ("_ \<leftarrow> _") |
|
263 |
|
264 parse_translation (advanced) {* |
|
265 let |
|
266 val femptyC = Syntax.const @{const_name fempty}; |
|
267 val finsertC = Syntax.const @{const_name finsert}; |
|
268 val fmapC = Syntax.const @{const_name fmap}; |
|
269 val fconcatC = Syntax.const @{const_name fconcat}; |
|
270 val IfC = Syntax.const @{const_name If}; |
|
271 fun fsingl x = finsertC $ x $ femptyC; |
|
272 |
|
273 fun pat_tr ctxt p e opti = (* %x. case x of p => e | _ => [] *) |
|
274 let |
|
275 val x = Free (Name.variant (fold Term.add_free_names [p, e] []) "x", dummyT); |
|
276 val e = if opti then fsingl e else e; |
|
277 val case1 = Syntax.const "_case1" $ p $ e; |
|
278 val case2 = Syntax.const "_case1" $ Syntax.const Term.dummy_patternN |
|
279 $ femptyC; |
|
280 val cs = Syntax.const "_case2" $ case1 $ case2 |
|
281 val ft = Datatype_Case.case_tr false Datatype.info_of_constr |
|
282 ctxt [x, cs] |
|
283 in lambda x ft end; |
|
284 |
|
285 fun abs_tr ctxt (p as Free(s,T)) e opti = |
|
286 let val thy = ProofContext.theory_of ctxt; |
|
287 val s' = Sign.intern_const thy s |
|
288 in if Sign.declared_const thy s' |
|
289 then (pat_tr ctxt p e opti, false) |
|
290 else (lambda p e, true) |
|
291 end |
|
292 | abs_tr ctxt p e opti = (pat_tr ctxt p e opti, false); |
|
293 |
|
294 fun fsc_tr ctxt [e, Const("_fsc_test",_) $ b, qs] = |
|
295 let |
|
296 val res = case qs of |
|
297 Const("_fsc_end",_) => fsingl e |
|
298 | Const("_fsc_quals",_)$ q $ qs => fsc_tr ctxt [e, q, qs]; |
|
299 in |
|
300 IfC $ b $ res $ femptyC |
|
301 end |
|
302 |
|
303 | fsc_tr ctxt [e, Const("_fsc_gen",_) $ p $ es, Const("_fsc_end",_)] = |
|
304 (case abs_tr ctxt p e true of |
|
305 (f,true) => fmapC $ f $ es |
|
306 | (f, false) => fconcatC $ (fmapC $ f $ es)) |
|
307 |
|
308 | fsc_tr ctxt [e, Const("_fsc_gen",_) $ p $ es, Const("_fsc_quals",_) $ q $ qs] = |
|
309 let |
|
310 val e' = fsc_tr ctxt [e, q, qs]; |
|
311 in |
|
312 fconcatC $ (fmapC $ (fst (abs_tr ctxt p e' false)) $ es) |
|
313 end |
|
314 |
|
315 in [("_fsetcompr", fsc_tr)] end |
|
316 *} |
|
317 |
|
318 (* examles *) |
|
319 term "{|(x,y,z). b|}" |
|
320 term "{|x. x \<leftarrow> xs|}" |
|
321 term "{|(x,y,z). x\<leftarrow>xs|}" |
|
322 term "{|e x y. x\<leftarrow>xs, y\<leftarrow>ys|}" |
|
323 term "{|(x,y,z). x<a, x>b|}" |
|
324 term "{|(x,y,z). x\<leftarrow>xs, x>b|}" |
|
325 term "{|(x,y,z). x<a, x\<leftarrow>xs|}" |
|
326 term "{|(x,y). Cons True x \<leftarrow> xs|}" |
|
327 term "{|(x,y,z). Cons x [] \<leftarrow> xs|}" |
|
328 term "{|(x,y,z). x<a, x>b, x=d|}" |
|
329 term "{|(x,y,z). x<a, x>b, y\<leftarrow>ys|}" |
|
330 term "{|(x,y,z). x<a, x\<leftarrow>xs,y>b|}" |
|
331 term "{|(x,y,z). x<a, x\<leftarrow>xs, y\<leftarrow>ys|}" |
|
332 term "{|(x,y,z). x\<leftarrow>xs, x>b, y<a|}" |
|
333 term "{|(x,y,z). x\<leftarrow>xs, x>b, y\<leftarrow>ys|}" |
|
334 term "{|(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,y>x|}" |
|
335 term "{|(x,y,z). x\<leftarrow>xs, y\<leftarrow>ys,z\<leftarrow>zs|}" |
|
336 |
|
337 |
|
338 (* BELOW CONSTRUCTION SITE *) |
34 |
339 |
35 |
340 |
36 lemma no_mem_nil: |
341 lemma no_mem_nil: |
37 "(\<forall>a. a \<notin> set A) = (A = [])" |
342 "(\<forall>a. a \<notin> set A) = (A = [])" |
38 by (induct A) (auto) |
343 by (induct A) (auto) |