40 NOT fm| And fm fm| Or fm fm| Imp fm fm| Iff fm fm| E fm| A fm |
40 NOT fm| And fm fm| Or fm fm| Imp fm fm| Iff fm fm| E fm| A fm |
41 | Closed nat | NClosed nat |
41 | Closed nat | NClosed nat |
42 |
42 |
43 |
43 |
44 (* A size for fm *) |
44 (* A size for fm *) |
45 consts fmsize :: "fm \<Rightarrow> nat" |
45 fun fmsize :: "fm \<Rightarrow> nat" where |
46 recdef fmsize "measure size" |
|
47 "fmsize (NOT p) = 1 + fmsize p" |
46 "fmsize (NOT p) = 1 + fmsize p" |
48 "fmsize (And p q) = 1 + fmsize p + fmsize q" |
47 | "fmsize (And p q) = 1 + fmsize p + fmsize q" |
49 "fmsize (Or p q) = 1 + fmsize p + fmsize q" |
48 | "fmsize (Or p q) = 1 + fmsize p + fmsize q" |
50 "fmsize (Imp p q) = 3 + fmsize p + fmsize q" |
49 | "fmsize (Imp p q) = 3 + fmsize p + fmsize q" |
51 "fmsize (Iff p q) = 3 + 2*(fmsize p + fmsize q)" |
50 | "fmsize (Iff p q) = 3 + 2*(fmsize p + fmsize q)" |
52 "fmsize (E p) = 1 + fmsize p" |
51 | "fmsize (E p) = 1 + fmsize p" |
53 "fmsize (A p) = 4+ fmsize p" |
52 | "fmsize (A p) = 4+ fmsize p" |
54 "fmsize (Dvd i t) = 2" |
53 | "fmsize (Dvd i t) = 2" |
55 "fmsize (NDvd i t) = 2" |
54 | "fmsize (NDvd i t) = 2" |
56 "fmsize p = 1" |
55 | "fmsize p = 1" |
57 (* several lemmas about fmsize *) |
56 (* several lemmas about fmsize *) |
58 lemma fmsize_pos: "fmsize p > 0" |
57 lemma fmsize_pos: "fmsize p > 0" |
59 by (induct p rule: fmsize.induct) simp_all |
58 by (induct p rule: fmsize.induct) simp_all |
60 |
59 |
61 (* Semantics of formulae (fm) *) |
60 (* Semantics of formulae (fm) *) |
109 lemma prep: "Ifm bbs bs (prep p) = Ifm bbs bs p" |
108 lemma prep: "Ifm bbs bs (prep p) = Ifm bbs bs p" |
110 by (induct p arbitrary: bs rule: prep.induct, auto) |
109 by (induct p arbitrary: bs rule: prep.induct, auto) |
111 |
110 |
112 |
111 |
113 (* Quantifier freeness *) |
112 (* Quantifier freeness *) |
114 consts qfree:: "fm \<Rightarrow> bool" |
113 fun qfree:: "fm \<Rightarrow> bool" where |
115 recdef qfree "measure size" |
|
116 "qfree (E p) = False" |
114 "qfree (E p) = False" |
117 "qfree (A p) = False" |
115 | "qfree (A p) = False" |
118 "qfree (NOT p) = qfree p" |
116 | "qfree (NOT p) = qfree p" |
119 "qfree (And p q) = (qfree p \<and> qfree q)" |
117 | "qfree (And p q) = (qfree p \<and> qfree q)" |
120 "qfree (Or p q) = (qfree p \<and> qfree q)" |
118 | "qfree (Or p q) = (qfree p \<and> qfree q)" |
121 "qfree (Imp p q) = (qfree p \<and> qfree q)" |
119 | "qfree (Imp p q) = (qfree p \<and> qfree q)" |
122 "qfree (Iff p q) = (qfree p \<and> qfree q)" |
120 | "qfree (Iff p q) = (qfree p \<and> qfree q)" |
123 "qfree p = True" |
121 | "qfree p = True" |
124 |
122 |
125 (* Boundedness and substitution *) |
123 (* Boundedness and substitution *) |
126 |
124 |
127 primrec numbound0:: "num \<Rightarrow> bool" (* a num is INDEPENDENT of Bound 0 *) where |
125 primrec numbound0:: "num \<Rightarrow> bool" (* a num is INDEPENDENT of Bound 0 *) where |
128 "numbound0 (C c) = True" |
126 "numbound0 (C c) = True" |
205 lemma subst0_I: assumes qfp: "qfree p" |
203 lemma subst0_I: assumes qfp: "qfree p" |
206 shows "Ifm bbs (b#bs) (subst0 a p) = Ifm bbs ((Inum (b#bs) a)#bs) p" |
204 shows "Ifm bbs (b#bs) (subst0 a p) = Ifm bbs ((Inum (b#bs) a)#bs) p" |
207 using qfp numsubst0_I[where b="b" and bs="bs" and a="a"] |
205 using qfp numsubst0_I[where b="b" and bs="bs" and a="a"] |
208 by (induct p) (simp_all add: gr0_conv_Suc) |
206 by (induct p) (simp_all add: gr0_conv_Suc) |
209 |
207 |
210 |
208 fun decrnum:: "num \<Rightarrow> num" where |
211 consts |
|
212 decrnum:: "num \<Rightarrow> num" |
|
213 decr :: "fm \<Rightarrow> fm" |
|
214 |
|
215 recdef decrnum "measure size" |
|
216 "decrnum (Bound n) = Bound (n - 1)" |
209 "decrnum (Bound n) = Bound (n - 1)" |
217 "decrnum (Neg a) = Neg (decrnum a)" |
210 | "decrnum (Neg a) = Neg (decrnum a)" |
218 "decrnum (Add a b) = Add (decrnum a) (decrnum b)" |
211 | "decrnum (Add a b) = Add (decrnum a) (decrnum b)" |
219 "decrnum (Sub a b) = Sub (decrnum a) (decrnum b)" |
212 | "decrnum (Sub a b) = Sub (decrnum a) (decrnum b)" |
220 "decrnum (Mul c a) = Mul c (decrnum a)" |
213 | "decrnum (Mul c a) = Mul c (decrnum a)" |
221 "decrnum (CN n i a) = (CN (n - 1) i (decrnum a))" |
214 | "decrnum (CN n i a) = (CN (n - 1) i (decrnum a))" |
222 "decrnum a = a" |
215 | "decrnum a = a" |
223 |
216 |
224 recdef decr "measure size" |
217 fun decr :: "fm \<Rightarrow> fm" where |
225 "decr (Lt a) = Lt (decrnum a)" |
218 "decr (Lt a) = Lt (decrnum a)" |
226 "decr (Le a) = Le (decrnum a)" |
219 | "decr (Le a) = Le (decrnum a)" |
227 "decr (Gt a) = Gt (decrnum a)" |
220 | "decr (Gt a) = Gt (decrnum a)" |
228 "decr (Ge a) = Ge (decrnum a)" |
221 | "decr (Ge a) = Ge (decrnum a)" |
229 "decr (Eq a) = Eq (decrnum a)" |
222 | "decr (Eq a) = Eq (decrnum a)" |
230 "decr (NEq a) = NEq (decrnum a)" |
223 | "decr (NEq a) = NEq (decrnum a)" |
231 "decr (Dvd i a) = Dvd i (decrnum a)" |
224 | "decr (Dvd i a) = Dvd i (decrnum a)" |
232 "decr (NDvd i a) = NDvd i (decrnum a)" |
225 | "decr (NDvd i a) = NDvd i (decrnum a)" |
233 "decr (NOT p) = NOT (decr p)" |
226 | "decr (NOT p) = NOT (decr p)" |
234 "decr (And p q) = And (decr p) (decr q)" |
227 | "decr (And p q) = And (decr p) (decr q)" |
235 "decr (Or p q) = Or (decr p) (decr q)" |
228 | "decr (Or p q) = Or (decr p) (decr q)" |
236 "decr (Imp p q) = Imp (decr p) (decr q)" |
229 | "decr (Imp p q) = Imp (decr p) (decr q)" |
237 "decr (Iff p q) = Iff (decr p) (decr q)" |
230 | "decr (Iff p q) = Iff (decr p) (decr q)" |
238 "decr p = p" |
231 | "decr p = p" |
239 |
232 |
240 lemma decrnum: assumes nb: "numbound0 t" |
233 lemma decrnum: assumes nb: "numbound0 t" |
241 shows "Inum (x#bs) t = Inum bs (decrnum t)" |
234 shows "Inum (x#bs) t = Inum bs (decrnum t)" |
242 using nb by (induct t rule: decrnum.induct, auto simp add: gr0_conv_Suc) |
235 using nb by (induct t rule: decrnum.induct, auto simp add: gr0_conv_Suc) |
243 |
236 |
247 by (induct p rule: decr.induct, simp_all add: gr0_conv_Suc decrnum) |
240 by (induct p rule: decr.induct, simp_all add: gr0_conv_Suc decrnum) |
248 |
241 |
249 lemma decr_qf: "bound0 p \<Longrightarrow> qfree (decr p)" |
242 lemma decr_qf: "bound0 p \<Longrightarrow> qfree (decr p)" |
250 by (induct p, simp_all) |
243 by (induct p, simp_all) |
251 |
244 |
252 consts |
245 fun isatom :: "fm \<Rightarrow> bool" (* test for atomicity *) where |
253 isatom :: "fm \<Rightarrow> bool" (* test for atomicity *) |
|
254 recdef isatom "measure size" |
|
255 "isatom T = True" |
246 "isatom T = True" |
256 "isatom F = True" |
247 | "isatom F = True" |
257 "isatom (Lt a) = True" |
248 | "isatom (Lt a) = True" |
258 "isatom (Le a) = True" |
249 | "isatom (Le a) = True" |
259 "isatom (Gt a) = True" |
250 | "isatom (Gt a) = True" |
260 "isatom (Ge a) = True" |
251 | "isatom (Ge a) = True" |
261 "isatom (Eq a) = True" |
252 | "isatom (Eq a) = True" |
262 "isatom (NEq a) = True" |
253 | "isatom (NEq a) = True" |
263 "isatom (Dvd i b) = True" |
254 | "isatom (Dvd i b) = True" |
264 "isatom (NDvd i b) = True" |
255 | "isatom (NDvd i b) = True" |
265 "isatom (Closed P) = True" |
256 | "isatom (Closed P) = True" |
266 "isatom (NClosed P) = True" |
257 | "isatom (NClosed P) = True" |
267 "isatom p = False" |
258 | "isatom p = False" |
268 |
259 |
269 lemma numsubst0_numbound0: assumes nb: "numbound0 t" |
260 lemma numsubst0_numbound0: assumes nb: "numbound0 t" |
270 shows "numbound0 (numsubst0 t a)" |
261 shows "numbound0 (numsubst0 t a)" |
271 using nb apply (induct a) |
262 using nb apply (induct a) |
272 apply simp_all |
263 apply simp_all |
302 lemma evaldjf_qf: |
293 lemma evaldjf_qf: |
303 assumes nb: "\<forall> x\<in> set xs. qfree (f x)" |
294 assumes nb: "\<forall> x\<in> set xs. qfree (f x)" |
304 shows "qfree (evaldjf f xs)" |
295 shows "qfree (evaldjf f xs)" |
305 using nb by (induct xs, auto simp add: evaldjf_def djf_def Let_def) (case_tac "f a", auto) |
296 using nb by (induct xs, auto simp add: evaldjf_def djf_def Let_def) (case_tac "f a", auto) |
306 |
297 |
307 consts disjuncts :: "fm \<Rightarrow> fm list" |
298 fun disjuncts :: "fm \<Rightarrow> fm list" where |
308 recdef disjuncts "measure size" |
|
309 "disjuncts (Or p q) = (disjuncts p) @ (disjuncts q)" |
299 "disjuncts (Or p q) = (disjuncts p) @ (disjuncts q)" |
310 "disjuncts F = []" |
300 | "disjuncts F = []" |
311 "disjuncts p = [p]" |
301 | "disjuncts p = [p]" |
312 |
302 |
313 lemma disjuncts: "(\<exists> q\<in> set (disjuncts p). Ifm bbs bs q) = Ifm bbs bs p" |
303 lemma disjuncts: "(\<exists> q\<in> set (disjuncts p). Ifm bbs bs q) = Ifm bbs bs p" |
314 by(induct p rule: disjuncts.induct, auto) |
304 by(induct p rule: disjuncts.induct, auto) |
315 |
305 |
316 lemma disjuncts_nb: "bound0 p \<Longrightarrow> \<forall> q\<in> set (disjuncts p). bound0 q" |
306 lemma disjuncts_nb: "bound0 p \<Longrightarrow> \<forall> q\<in> set (disjuncts p). bound0 q" |
367 finally show "qfree (DJ qe p) \<and> Ifm bbs bs (DJ qe p) = Ifm bbs bs (E p)" using qfth by blast |
357 finally show "qfree (DJ qe p) \<and> Ifm bbs bs (DJ qe p) = Ifm bbs bs (E p)" using qfth by blast |
368 qed |
358 qed |
369 (* Simplification *) |
359 (* Simplification *) |
370 |
360 |
371 (* Algebraic simplifications for nums *) |
361 (* Algebraic simplifications for nums *) |
372 consts bnds:: "num \<Rightarrow> nat list" |
362 |
373 lex_ns:: "nat list \<times> nat list \<Rightarrow> bool" |
363 fun bnds:: "num \<Rightarrow> nat list" where |
374 recdef bnds "measure size" |
|
375 "bnds (Bound n) = [n]" |
364 "bnds (Bound n) = [n]" |
376 "bnds (CN n c a) = n#(bnds a)" |
365 | "bnds (CN n c a) = n#(bnds a)" |
377 "bnds (Neg a) = bnds a" |
366 | "bnds (Neg a) = bnds a" |
378 "bnds (Add a b) = (bnds a)@(bnds b)" |
367 | "bnds (Add a b) = (bnds a)@(bnds b)" |
379 "bnds (Sub a b) = (bnds a)@(bnds b)" |
368 | "bnds (Sub a b) = (bnds a)@(bnds b)" |
380 "bnds (Mul i a) = bnds a" |
369 | "bnds (Mul i a) = bnds a" |
381 "bnds a = []" |
370 | "bnds a = []" |
382 recdef lex_ns "measure (\<lambda> (xs,ys). length xs + length ys)" |
371 |
383 "lex_ns ([], ms) = True" |
372 fun lex_ns:: "nat list \<Rightarrow> nat list \<Rightarrow> bool" where |
384 "lex_ns (ns, []) = False" |
373 "lex_ns [] ms = True" |
385 "lex_ns (n#ns, m#ms) = (n<m \<or> ((n = m) \<and> lex_ns (ns,ms))) " |
374 | "lex_ns ns [] = False" |
|
375 | "lex_ns (n#ns) (m#ms) = (n<m \<or> ((n = m) \<and> lex_ns ns ms)) " |
386 definition lex_bnd :: "num \<Rightarrow> num \<Rightarrow> bool" where |
376 definition lex_bnd :: "num \<Rightarrow> num \<Rightarrow> bool" where |
387 "lex_bnd t s \<equiv> lex_ns (bnds t, bnds s)" |
377 "lex_bnd t s \<equiv> lex_ns (bnds t) (bnds s)" |
388 |
378 |
389 consts |
379 consts |
390 numadd:: "num \<times> num \<Rightarrow> num" |
380 numadd:: "num \<times> num \<Rightarrow> num" |
391 recdef numadd "measure (\<lambda> (t,s). num_size t + num_size s)" |
381 recdef numadd "measure (\<lambda> (t,s). num_size t + num_size s)" |
392 "numadd (CN n1 c1 r1 ,CN n2 c2 r2) = |
382 "numadd (CN n1 c1 r1 ,CN n2 c2 r2) = |
428 done |
418 done |
429 |
419 |
430 lemma numadd_nb: "\<lbrakk> numbound0 t ; numbound0 s\<rbrakk> \<Longrightarrow> numbound0 (numadd (t,s))" |
420 lemma numadd_nb: "\<lbrakk> numbound0 t ; numbound0 s\<rbrakk> \<Longrightarrow> numbound0 (numadd (t,s))" |
431 by (induct t s rule: numadd.induct, auto simp add: Let_def) |
421 by (induct t s rule: numadd.induct, auto simp add: Let_def) |
432 |
422 |
433 fun |
423 fun nummul :: "int \<Rightarrow> num \<Rightarrow> num" where |
434 nummul :: "int \<Rightarrow> num \<Rightarrow> num" |
|
435 where |
|
436 "nummul i (C j) = C (i * j)" |
424 "nummul i (C j) = C (i * j)" |
437 | "nummul i (CN n c t) = CN n (c*i) (nummul i t)" |
425 | "nummul i (CN n c t) = CN n (c*i) (nummul i t)" |
438 | "nummul i t = Mul i t" |
426 | "nummul i t = Mul i t" |
439 |
427 |
440 lemma nummul: "\<And> i. Inum bs (nummul i t) = Inum bs (Mul i t)" |
428 lemma nummul: "\<And> i. Inum bs (nummul i t) = Inum bs (Mul i t)" |
441 by (induct t rule: nummul.induct, auto simp add: algebra_simps numadd) |
429 by (induct t rule: nummul.induct, auto simp add: algebra_simps numadd) |
442 |
430 |
443 lemma nummul_nb: "\<And> i. numbound0 t \<Longrightarrow> numbound0 (nummul i t)" |
431 lemma nummul_nb: "\<And> i. numbound0 t \<Longrightarrow> numbound0 (nummul i t)" |
681 lemma simpfm_qf: "qfree p \<Longrightarrow> qfree (simpfm p)" |
669 lemma simpfm_qf: "qfree p \<Longrightarrow> qfree (simpfm p)" |
682 by (induct p rule: simpfm.induct, auto simp add: disj_qf imp_qf iff_qf conj_qf not_qf Let_def) |
670 by (induct p rule: simpfm.induct, auto simp add: disj_qf imp_qf iff_qf conj_qf not_qf Let_def) |
683 (case_tac "simpnum a",auto)+ |
671 (case_tac "simpnum a",auto)+ |
684 |
672 |
685 (* Generic quantifier elimination *) |
673 (* Generic quantifier elimination *) |
686 consts qelim :: "fm \<Rightarrow> (fm \<Rightarrow> fm) \<Rightarrow> fm" |
674 function (sequential) qelim :: "fm \<Rightarrow> (fm \<Rightarrow> fm) \<Rightarrow> fm" where |
687 recdef qelim "measure fmsize" |
|
688 "qelim (E p) = (\<lambda> qe. DJ qe (qelim p qe))" |
675 "qelim (E p) = (\<lambda> qe. DJ qe (qelim p qe))" |
689 "qelim (A p) = (\<lambda> qe. not (qe ((qelim (NOT p) qe))))" |
676 | "qelim (A p) = (\<lambda> qe. not (qe ((qelim (NOT p) qe))))" |
690 "qelim (NOT p) = (\<lambda> qe. not (qelim p qe))" |
677 | "qelim (NOT p) = (\<lambda> qe. not (qelim p qe))" |
691 "qelim (And p q) = (\<lambda> qe. conj (qelim p qe) (qelim q qe))" |
678 | "qelim (And p q) = (\<lambda> qe. conj (qelim p qe) (qelim q qe))" |
692 "qelim (Or p q) = (\<lambda> qe. disj (qelim p qe) (qelim q qe))" |
679 | "qelim (Or p q) = (\<lambda> qe. disj (qelim p qe) (qelim q qe))" |
693 "qelim (Imp p q) = (\<lambda> qe. imp (qelim p qe) (qelim q qe))" |
680 | "qelim (Imp p q) = (\<lambda> qe. imp (qelim p qe) (qelim q qe))" |
694 "qelim (Iff p q) = (\<lambda> qe. iff (qelim p qe) (qelim q qe))" |
681 | "qelim (Iff p q) = (\<lambda> qe. iff (qelim p qe) (qelim q qe))" |
695 "qelim p = (\<lambda> y. simpfm p)" |
682 | "qelim p = (\<lambda> y. simpfm p)" |
696 |
|
697 (*function (sequential) |
|
698 qelim :: "(fm \<Rightarrow> fm) \<Rightarrow> fm \<Rightarrow> fm" |
|
699 where |
|
700 "qelim qe (E p) = DJ qe (qelim qe p)" |
|
701 | "qelim qe (A p) = not (qe ((qelim qe (NOT p))))" |
|
702 | "qelim qe (NOT p) = not (qelim qe p)" |
|
703 | "qelim qe (And p q) = conj (qelim qe p) (qelim qe q)" |
|
704 | "qelim qe (Or p q) = disj (qelim qe p) (qelim qe q)" |
|
705 | "qelim qe (Imp p q) = imp (qelim qe p) (qelim qe q)" |
|
706 | "qelim qe (Iff p q) = iff (qelim qe p) (qelim qe q)" |
|
707 | "qelim qe p = simpfm p" |
|
708 by pat_completeness auto |
683 by pat_completeness auto |
709 termination by (relation "measure (fmsize o snd)") auto*) |
684 termination by (relation "measure fmsize") auto |
710 |
685 |
711 lemma qelim_ci: |
686 lemma qelim_ci: |
712 assumes qe_inv: "\<forall> bs p. qfree p \<longrightarrow> qfree (qe p) \<and> (Ifm bbs bs (qe p) = Ifm bbs bs (E p))" |
687 assumes qe_inv: "\<forall> bs p. qfree p \<longrightarrow> qfree (qe p) \<and> (Ifm bbs bs (qe p) = Ifm bbs bs (E p))" |
713 shows "\<And> bs. qfree (qelim p qe) \<and> (Ifm bbs bs (qelim p qe) = Ifm bbs bs p)" |
688 shows "\<And> bs. qfree (qelim p qe) \<and> (Ifm bbs bs (qelim p qe) = Ifm bbs bs p)" |
714 using qe_inv DJ_qe[OF qe_inv] |
689 using qe_inv DJ_qe[OF qe_inv] |
715 by(induct p rule: qelim.induct) |
690 by(induct p rule: qelim.induct) |
716 (auto simp add: not disj conj iff imp not_qf disj_qf conj_qf imp_qf iff_qf |
691 (auto simp add: not disj conj iff imp not_qf disj_qf conj_qf imp_qf iff_qf |
717 simpfm simpfm_qf simp del: simpfm.simps) |
692 simpfm simpfm_qf simp del: simpfm.simps) |
718 (* Linearity for fm where Bound 0 ranges over \<int> *) |
693 (* Linearity for fm where Bound 0 ranges over \<int> *) |
719 |
694 |
720 fun |
695 fun zsplit0 :: "num \<Rightarrow> int \<times> num" (* splits the bounded from the unbounded part*) |
721 zsplit0 :: "num \<Rightarrow> int \<times> num" (* splits the bounded from the unbounded part*) |
|
722 where |
696 where |
723 "zsplit0 (C c) = (0,C c)" |
697 "zsplit0 (C c) = (0,C c)" |
724 | "zsplit0 (Bound n) = (if n=0 then (1, C 0) else (0,Bound n))" |
698 | "zsplit0 (Bound n) = (if n=0 then (1, C 0) else (0,Bound n))" |
725 | "zsplit0 (CN n i a) = |
699 | "zsplit0 (CN n i a) = |
726 (let (i',a') = zsplit0 a |
700 (let (i',a') = zsplit0 a |