src/HOL/Decision_Procs/Cooper.thy
changeset 41837 6fc224dc5473
parent 41836 c9d788ff7940
child 42284 326f57825e1a
equal deleted inserted replaced
41836:c9d788ff7940 41837:6fc224dc5473
    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