products/Sources/formale Sprachen/Isabelle/HOL/Decision_Procs image not shown  

Quellcode-Bibliothek

© Kompilation durch diese Firma

[Weder Korrektheit noch Funktionsfähigkeit der Software werden zugesichert.]

Datei: sdl006.cob   Sprache: Isabelle

Original von: Isabelle©

(*  Title:      HOL/Decision_Procs/Cooper.thy
    Author:     Amine Chaieb
*)


section \<open>Presburger arithmetic based on Cooper's algorithm\<close>

theory Cooper
imports
  Complex_Main
  "HOL-Library.Code_Target_Numeral"
begin

subsection \<open>Basic formulae\<close>

datatype (plugins del: size) num = C int | Bound nat | CN nat int num
  | Neg num | Add num num | Sub num num
  | Mul int num

instantiation num :: size
begin

primrec size_num :: "num \ nat"
  where
    "size_num (C c) = 1"
  | "size_num (Bound n) = 1"
  | "size_num (Neg a) = 1 + size_num a"
  | "size_num (Add a b) = 1 + size_num a + size_num b"
  | "size_num (Sub a b) = 3 + size_num a + size_num b"
  | "size_num (CN n c a) = 4 + size_num a"
  | "size_num (Mul c a) = 1 + size_num a"

instance ..

end

primrec Inum :: "int list \ num \ int"
  where
    "Inum bs (C c) = c"
  | "Inum bs (Bound n) = bs ! n"
  | "Inum bs (CN n c a) = c * (bs ! n) + Inum bs a"
  | "Inum bs (Neg a) = - Inum bs a"
  | "Inum bs (Add a b) = Inum bs a + Inum bs b"
  | "Inum bs (Sub a b) = Inum bs a - Inum bs b"
  | "Inum bs (Mul c a) = c * Inum bs a"

datatype (plugins del: size) fm = T | F
  | Lt num | Le num | Gt num | Ge num | Eq num | NEq num
  | Dvd int num | NDvd int num
  | NOT fm | And fm fm | Or fm fm | Imp fm fm | Iff fm fm
  | E fm | A fm | Closed nat | NClosed nat

instantiation fm :: size
begin

primrec size_fm :: "fm \ nat"
  where
    "size_fm (NOT p) = 1 + size_fm p"
  | "size_fm (And p q) = 1 + size_fm p + size_fm q"
  | "size_fm (Or p q) = 1 + size_fm p + size_fm q"
  | "size_fm (Imp p q) = 3 + size_fm p + size_fm q"
  | "size_fm (Iff p q) = 3 + 2 * (size_fm p + size_fm q)"
  | "size_fm (E p) = 1 + size_fm p"
  | "size_fm (A p) = 4 + size_fm p"
  | "size_fm (Dvd i t) = 2"
  | "size_fm (NDvd i t) = 2"
  | "size_fm T = 1"
  | "size_fm F = 1"
  | "size_fm (Lt _) = 1"
  | "size_fm (Le _) = 1"
  | "size_fm (Gt _) = 1"
  | "size_fm (Ge _) = 1"
  | "size_fm (Eq _) = 1"
  | "size_fm (NEq _) = 1"
  | "size_fm (Closed _) = 1"
  | "size_fm (NClosed _) = 1"

instance ..

end

lemma fmsize_pos [simp]: "size p > 0"
  for p :: fm
  by (induct p) simp_all

primrec Ifm :: "bool list \ int list \ fm \ bool" \ \Semantics of formulae (\fm\)\
  where
    "Ifm bbs bs T \ True"
  | "Ifm bbs bs F \ False"
  | "Ifm bbs bs (Lt a) \ Inum bs a < 0"
  | "Ifm bbs bs (Gt a) \ Inum bs a > 0"
  | "Ifm bbs bs (Le a) \ Inum bs a \ 0"
  | "Ifm bbs bs (Ge a) \ Inum bs a \ 0"
  | "Ifm bbs bs (Eq a) \ Inum bs a = 0"
  | "Ifm bbs bs (NEq a) \ Inum bs a \ 0"
  | "Ifm bbs bs (Dvd i b) \ i dvd Inum bs b"
  | "Ifm bbs bs (NDvd i b) \ \ i dvd Inum bs b"
  | "Ifm bbs bs (NOT p) \ \ Ifm bbs bs p"
  | "Ifm bbs bs (And p q) \ Ifm bbs bs p \ Ifm bbs bs q"
  | "Ifm bbs bs (Or p q) \ Ifm bbs bs p \ Ifm bbs bs q"
  | "Ifm bbs bs (Imp p q) \ (Ifm bbs bs p \ Ifm bbs bs q)"
  | "Ifm bbs bs (Iff p q) \ Ifm bbs bs p = Ifm bbs bs q"
  | "Ifm bbs bs (E p) \ (\x. Ifm bbs (x # bs) p)"
  | "Ifm bbs bs (A p) \ (\x. Ifm bbs (x # bs) p)"
  | "Ifm bbs bs (Closed n) \ bbs ! n"
  | "Ifm bbs bs (NClosed n) \ \ bbs ! n"

fun prep :: "fm \ fm"
  where
    "prep (E T) = T"
  | "prep (E F) = F"
  | "prep (E (Or p q)) = Or (prep (E p)) (prep (E q))"
  | "prep (E (Imp p q)) = Or (prep (E (NOT p))) (prep (E q))"
  | "prep (E (Iff p q)) = Or (prep (E (And p q))) (prep (E (And (NOT p) (NOT q))))"
  | "prep (E (NOT (And p q))) = Or (prep (E (NOT p))) (prep (E(NOT q)))"
  | "prep (E (NOT (Imp p q))) = prep (E (And p (NOT q)))"
  | "prep (E (NOT (Iff p q))) = Or (prep (E (And p (NOT q)))) (prep (E(And (NOT p) q)))"
  | "prep (E p) = E (prep p)"
  | "prep (A (And p q)) = And (prep (A p)) (prep (A q))"
  | "prep (A p) = prep (NOT (E (NOT p)))"
  | "prep (NOT (NOT p)) = prep p"
  | "prep (NOT (And p q)) = Or (prep (NOT p)) (prep (NOT q))"
  | "prep (NOT (A p)) = prep (E (NOT p))"
  | "prep (NOT (Or p q)) = And (prep (NOT p)) (prep (NOT q))"
  | "prep (NOT (Imp p q)) = And (prep p) (prep (NOT q))"
  | "prep (NOT (Iff p q)) = Or (prep (And p (NOT q))) (prep (And (NOT p) q))"
  | "prep (NOT p) = NOT (prep p)"
  | "prep (Or p q) = Or (prep p) (prep q)"
  | "prep (And p q) = And (prep p) (prep q)"
  | "prep (Imp p q) = prep (Or (NOT p) q)"
  | "prep (Iff p q) = Or (prep (And p q)) (prep (And (NOT p) (NOT q)))"
  | "prep p = p"

lemma prep: "Ifm bbs bs (prep p) = Ifm bbs bs p"
  by (induct p arbitrary: bs rule: prep.induct) auto


fun qfree :: "fm \ bool" \ \Quantifier freeness\
  where
    "qfree (E p) \ False"
  | "qfree (A p) \ False"
  | "qfree (NOT p) \ qfree p"
  | "qfree (And p q) \ qfree p \ qfree q"
  | "qfree (Or p q) \ qfree p \ qfree q"
  | "qfree (Imp p q) \ qfree p \ qfree q"
  | "qfree (Iff p q) \ qfree p \ qfree q"
  | "qfree p \ True"


subsection \<open>Boundedness and substitution\<close>

primrec numbound0 :: "num \ bool" \ \a \num\ is \<^emph>\independent\ of Bound 0\
  where
    "numbound0 (C c) \ True"
  | "numbound0 (Bound n) \ n > 0"
  | "numbound0 (CN n i a) \ n > 0 \ numbound0 a"
  | "numbound0 (Neg a) \ numbound0 a"
  | "numbound0 (Add a b) \ numbound0 a \ numbound0 b"
  | "numbound0 (Sub a b) \ numbound0 a \ numbound0 b"
  | "numbound0 (Mul i a) \ numbound0 a"

lemma numbound0_I:
  assumes "numbound0 a"
  shows "Inum (b # bs) a = Inum (b' # bs) a"
  using assms by (induct a rule: num.induct) (auto simp add: gr0_conv_Suc)

primrec bound0 :: "fm \ bool" \ \a formula is independent of Bound 0\
  where
    "bound0 T \ True"
  | "bound0 F \ True"
  | "bound0 (Lt a) \ numbound0 a"
  | "bound0 (Le a) \ numbound0 a"
  | "bound0 (Gt a) \ numbound0 a"
  | "bound0 (Ge a) \ numbound0 a"
  | "bound0 (Eq a) \ numbound0 a"
  | "bound0 (NEq a) \ numbound0 a"
  | "bound0 (Dvd i a) \ numbound0 a"
  | "bound0 (NDvd i a) \ numbound0 a"
  | "bound0 (NOT p) \ bound0 p"
  | "bound0 (And p q) \ bound0 p \ bound0 q"
  | "bound0 (Or p q) \ bound0 p \ bound0 q"
  | "bound0 (Imp p q) \ bound0 p \ bound0 q"
  | "bound0 (Iff p q) \ bound0 p \ bound0 q"
  | "bound0 (E p) \ False"
  | "bound0 (A p) \ False"
  | "bound0 (Closed P) \ True"
  | "bound0 (NClosed P) \ True"

lemma bound0_I:
  assumes "bound0 p"
  shows "Ifm bbs (b # bs) p = Ifm bbs (b' # bs) p"
  using assms numbound0_I[where b="b" and bs="bs" and b'="b'"]
  by (induct p rule: fm.induct) (auto simp add: gr0_conv_Suc)

fun numsubst0 :: "num \ num \ num"
  where
    "numsubst0 t (C c) = (C c)"
  | "numsubst0 t (Bound n) = (if n = 0 then t else Bound n)"
  | "numsubst0 t (CN 0 i a) = Add (Mul i t) (numsubst0 t a)"
  | "numsubst0 t (CN n i a) = CN n i (numsubst0 t a)"
  | "numsubst0 t (Neg a) = Neg (numsubst0 t a)"
  | "numsubst0 t (Add a b) = Add (numsubst0 t a) (numsubst0 t b)"
  | "numsubst0 t (Sub a b) = Sub (numsubst0 t a) (numsubst0 t b)"
  | "numsubst0 t (Mul i a) = Mul i (numsubst0 t a)"

lemma numsubst0_I: "Inum (b # bs) (numsubst0 a t) = Inum ((Inum (b # bs) a) # bs) t"
  by (induct t rule: numsubst0.induct) (auto simp: nth_Cons')

lemma numsubst0_I': "numbound0 a \ Inum (b#bs) (numsubst0 a t) = Inum ((Inum (b'#bs) a)#bs) t"
  by (induct t rule: numsubst0.induct) (auto simp: nth_Cons' numbound0_I[where b="b" and b'="b'"])

primrec subst0:: "num \ fm \ fm" \ \substitute a \num\ into a formula for Bound 0\
  where
    "subst0 t T = T"
  | "subst0 t F = F"
  | "subst0 t (Lt a) = Lt (numsubst0 t a)"
  | "subst0 t (Le a) = Le (numsubst0 t a)"
  | "subst0 t (Gt a) = Gt (numsubst0 t a)"
  | "subst0 t (Ge a) = Ge (numsubst0 t a)"
  | "subst0 t (Eq a) = Eq (numsubst0 t a)"
  | "subst0 t (NEq a) = NEq (numsubst0 t a)"
  | "subst0 t (Dvd i a) = Dvd i (numsubst0 t a)"
  | "subst0 t (NDvd i a) = NDvd i (numsubst0 t a)"
  | "subst0 t (NOT p) = NOT (subst0 t p)"
  | "subst0 t (And p q) = And (subst0 t p) (subst0 t q)"
  | "subst0 t (Or p q) = Or (subst0 t p) (subst0 t q)"
  | "subst0 t (Imp p q) = Imp (subst0 t p) (subst0 t q)"
  | "subst0 t (Iff p q) = Iff (subst0 t p) (subst0 t q)"
  | "subst0 t (Closed P) = (Closed P)"
  | "subst0 t (NClosed P) = (NClosed P)"

lemma subst0_I:
  assumes "qfree p"
  shows "Ifm bbs (b # bs) (subst0 a p) = Ifm bbs (Inum (b # bs) a # bs) p"
  using assms numsubst0_I[where b="b" and bs="bs" and a="a"]
  by (induct p) (simp_all add: gr0_conv_Suc)

fun decrnum:: "num \ num"
  where
    "decrnum (Bound n) = Bound (n - 1)"
  | "decrnum (Neg a) = Neg (decrnum a)"
  | "decrnum (Add a b) = Add (decrnum a) (decrnum b)"
  | "decrnum (Sub a b) = Sub (decrnum a) (decrnum b)"
  | "decrnum (Mul c a) = Mul c (decrnum a)"
  | "decrnum (CN n i a) = (CN (n - 1) i (decrnum a))"
  | "decrnum a = a"

fun decr :: "fm \ fm"
  where
    "decr (Lt a) = Lt (decrnum a)"
  | "decr (Le a) = Le (decrnum a)"
  | "decr (Gt a) = Gt (decrnum a)"
  | "decr (Ge a) = Ge (decrnum a)"
  | "decr (Eq a) = Eq (decrnum a)"
  | "decr (NEq a) = NEq (decrnum a)"
  | "decr (Dvd i a) = Dvd i (decrnum a)"
  | "decr (NDvd i a) = NDvd i (decrnum a)"
  | "decr (NOT p) = NOT (decr p)"
  | "decr (And p q) = And (decr p) (decr q)"
  | "decr (Or p q) = Or (decr p) (decr q)"
  | "decr (Imp p q) = Imp (decr p) (decr q)"
  | "decr (Iff p q) = Iff (decr p) (decr q)"
  | "decr p = p"

lemma decrnum:
  assumes "numbound0 t"
  shows "Inum (x # bs) t = Inum bs (decrnum t)"
  using assms by (induct t rule: decrnum.induct) (auto simp add: gr0_conv_Suc)

lemma decr:
  assumes assms: "bound0 p"
  shows "Ifm bbs (x # bs) p = Ifm bbs bs (decr p)"
  using assms by (induct p rule: decr.induct) (simp_all add: gr0_conv_Suc decrnum)

lemma decr_qf: "bound0 p \ qfree (decr p)"
  by (induct p) simp_all

fun isatom :: "fm \ bool" \ \test for atomicity\
  where
    "isatom T \ True"
  | "isatom F \ True"
  | "isatom (Lt a) \ True"
  | "isatom (Le a) \ True"
  | "isatom (Gt a) \ True"
  | "isatom (Ge a) \ True"
  | "isatom (Eq a) \ True"
  | "isatom (NEq a) \ True"
  | "isatom (Dvd i b) \ True"
  | "isatom (NDvd i b) \ True"
  | "isatom (Closed P) \ True"
  | "isatom (NClosed P) \ True"
  | "isatom p \ False"

lemma numsubst0_numbound0:
  assumes "numbound0 t"
  shows "numbound0 (numsubst0 t a)"
  using assms
proof (induct a)
  case (CN n)
  then show ?case by (cases n) simp_all
qed simp_all

lemma subst0_bound0:
  assumes qf: "qfree p"
    and nb: "numbound0 t"
  shows "bound0 (subst0 t p)"
  using qf numsubst0_numbound0[OF nb] by (induct p) auto

lemma bound0_qf: "bound0 p \ qfree p"
  by (induct p) simp_all


definition djf :: "('a \ fm) \ 'a \ fm \ fm"
where
  "djf f p q =
   (if q = T then T
    else if q = F then f p
    else
      let fp = f p
      in case fp of T \<Rightarrow> T | F \<Rightarrow> q | _ \<Rightarrow> Or (f p) q)"

definition evaldjf :: "('a \ fm) \ 'a list \ fm"
  where "evaldjf f ps = foldr (djf f) ps F"

lemma djf_Or: "Ifm bbs bs (djf f p q) = Ifm bbs bs (Or (f p) q)"
  by (cases "q=T", simp add: djf_def, cases "q = F", simp add: djf_def)
    (cases "f p", simp_all add: Let_def djf_def)

lemma evaldjf_ex: "Ifm bbs bs (evaldjf f ps) \ (\p \ set ps. Ifm bbs bs (f p))"
  by (induct ps) (simp_all add: evaldjf_def djf_Or)

lemma evaldjf_bound0:
  assumes nb: "\x\ set xs. bound0 (f x)"
  shows "bound0 (evaldjf f xs)"
  using nb by (induct xs) (auto simp add: evaldjf_def djf_def Let_def, case_tac "f a", auto)

lemma evaldjf_qf:
  assumes nb: "\x\ set xs. qfree (f x)"
  shows "qfree (evaldjf f xs)"
  using nb by (induct xs) (auto simp add: evaldjf_def djf_def Let_def, case_tac "f a", auto)

fun disjuncts :: "fm \ fm list"
  where
    "disjuncts (Or p q) = disjuncts p @ disjuncts q"
  | "disjuncts F = []"
  | "disjuncts p = [p]"

lemma disjuncts: "(\q \ set (disjuncts p). Ifm bbs bs q) \ Ifm bbs bs p"
  by (induct p rule: disjuncts.induct) auto

lemma disjuncts_nb:
  assumes "bound0 p"
  shows "\q \ set (disjuncts p). bound0 q"
proof -
  from assms have "list_all bound0 (disjuncts p)"
    by (induct p rule: disjuncts.induct) auto
  then show ?thesis
    by (simp only: list_all_iff)
qed

lemma disjuncts_qf:
  assumes "qfree p"
  shows "\q \ set (disjuncts p). qfree q"
proof -
  from assms have "list_all qfree (disjuncts p)"
    by (induct p rule: disjuncts.induct) auto
  then show ?thesis by (simp only: list_all_iff)
qed

definition DJ :: "(fm \ fm) \ fm \ fm"
  where "DJ f p = evaldjf f (disjuncts p)"

lemma DJ:
  assumes "\p q. f (Or p q) = Or (f p) (f q)"
    and "f F = F"
  shows "Ifm bbs bs (DJ f p) = Ifm bbs bs (f p)"
proof -
  have "Ifm bbs bs (DJ f p) \ (\q \ set (disjuncts p). Ifm bbs bs (f q))"
    by (simp add: DJ_def evaldjf_ex)
  also from assms have "\ = Ifm bbs bs (f p)"
    by (induct p rule: disjuncts.induct) auto
  finally show ?thesis .
qed

lemma DJ_qf:
  assumes "\p. qfree p \ qfree (f p)"
  shows "\p. qfree p \ qfree (DJ f p) "
proof clarify
  fix p
  assume qf: "qfree p"
  have th: "DJ f p = evaldjf f (disjuncts p)"
    by (simp add: DJ_def)
  from disjuncts_qf[OF qf] have "\q \ set (disjuncts p). qfree q" .
  with assms have th': "\q \ set (disjuncts p). qfree (f q)"
    by blast
  from evaldjf_qf[OF th'] th show "qfree (DJ f p)"
    by simp
qed

lemma DJ_qe:
  assumes qe: "\bs p. qfree p \ qfree (qe p) \ Ifm bbs bs (qe p) = Ifm bbs bs (E p)"
  shows "\bs p. qfree p \ qfree (DJ qe p) \ Ifm bbs bs ((DJ qe p)) = Ifm bbs bs (E p)"
proof clarify
  fix p :: fm
  fix bs
  assume qf: "qfree p"
  from qe have qth: "\p. qfree p \ qfree (qe p)"
    by blast
  from DJ_qf[OF qth] qf have qfth: "qfree (DJ qe p)"
    by auto
  have "Ifm bbs bs (DJ qe p) = (\q\ set (disjuncts p). Ifm bbs bs (qe q))"
    by (simp add: DJ_def evaldjf_ex)
  also have "\ \ (\q \ set (disjuncts p). Ifm bbs bs (E q))"
    using qe disjuncts_qf[OF qf] by auto
  also have "\ \ Ifm bbs bs (E p)"
    by (induct p rule: disjuncts.induct) auto
  finally show "qfree (DJ qe p) \ Ifm bbs bs (DJ qe p) = Ifm bbs bs (E p)"
    using qfth by blast
qed


subsection \<open>Simplification\<close>

text \<open>Algebraic simplifications for nums\<close>

fun bnds :: "num \ nat list"
  where
    "bnds (Bound n) = [n]"
  | "bnds (CN n c a) = n # bnds a"
  | "bnds (Neg a) = bnds a"
  | "bnds (Add a b) = bnds a @ bnds b"
  | "bnds (Sub a b) = bnds a @ bnds b"
  | "bnds (Mul i a) = bnds a"
  | "bnds a = []"

fun lex_ns:: "nat list \ nat list \ bool"
  where
    "lex_ns [] ms \ True"
  | "lex_ns ns [] \ False"
  | "lex_ns (n # ns) (m # ms) \ n < m \ (n = m \ lex_ns ns ms)"

definition lex_bnd :: "num \ num \ bool"
  where "lex_bnd t s = lex_ns (bnds t) (bnds s)"

fun numadd:: "num \ num \ num"
  where
    "numadd (CN n1 c1 r1) (CN n2 c2 r2) =
      (if n1 = n2 then
         let c = c1 + c2
         in if c = 0 then numadd r1 r2 else CN n1 c (numadd r1 r2)
       else if n1 \<le> n2 then CN n1 c1 (numadd r1 (Add (Mul c2 (Bound n2)) r2))
       else CN n2 c2 (numadd (Add (Mul c1 (Bound n1)) r1) r2))"
  | "numadd (CN n1 c1 r1) t = CN n1 c1 (numadd r1 t)"
  | "numadd t (CN n2 c2 r2) = CN n2 c2 (numadd t r2)"
  | "numadd (C b1) (C b2) = C (b1 + b2)"
  | "numadd a b = Add a b"

lemma numadd: "Inum bs (numadd t s) = Inum bs (Add t s)"
  by (induct t s rule: numadd.induct) (simp_all add: Let_def algebra_simps add_eq_0_iff)

lemma numadd_nb: "numbound0 t \ numbound0 s \ numbound0 (numadd t s)"
  by (induct t s rule: numadd.induct) (simp_all add: Let_def)

fun nummul :: "int \ num \ num"
  where
    "nummul i (C j) = C (i * j)"
  | "nummul i (CN n c t) = CN n (c * i) (nummul i t)"
  | "nummul i t = Mul i t"

lemma nummul: "Inum bs (nummul i t) = Inum bs (Mul i t)"
  by (induct t arbitrary: i rule: nummul.induct) (simp_all add: algebra_simps)

lemma nummul_nb: "numbound0 t \ numbound0 (nummul i t)"
  by (induct t arbitrary: i rule: nummul.induct) (simp_all add: numadd_nb)

definition numneg :: "num \ num"
  where "numneg t = nummul (- 1) t"

definition numsub :: "num \ num \ num"
  where "numsub s t = (if s = t then C 0 else numadd s (numneg t))"

lemma numneg: "Inum bs (numneg t) = Inum bs (Neg t)"
  using numneg_def nummul by simp

lemma numneg_nb: "numbound0 t \ numbound0 (numneg t)"
  using numneg_def nummul_nb by simp

lemma numsub: "Inum bs (numsub a b) = Inum bs (Sub a b)"
  using numneg numadd numsub_def by simp

lemma numsub_nb: "numbound0 t \ numbound0 s \ numbound0 (numsub t s)"
  using numsub_def numadd_nb numneg_nb by simp

fun simpnum :: "num \ num"
  where
    "simpnum (C j) = C j"
  | "simpnum (Bound n) = CN n 1 (C 0)"
  | "simpnum (Neg t) = numneg (simpnum t)"
  | "simpnum (Add t s) = numadd (simpnum t) (simpnum s)"
  | "simpnum (Sub t s) = numsub (simpnum t) (simpnum s)"
  | "simpnum (Mul i t) = (if i = 0 then C 0 else nummul i (simpnum t))"
  | "simpnum t = t"

lemma simpnum_ci: "Inum bs (simpnum t) = Inum bs t"
  by (induct t rule: simpnum.induct) (auto simp add: numneg numadd numsub nummul)

lemma simpnum_numbound0: "numbound0 t \ numbound0 (simpnum t)"
  by (induct t rule: simpnum.induct) (auto simp add: numadd_nb numsub_nb nummul_nb numneg_nb)

fun not :: "fm \ fm"
  where
    "not (NOT p) = p"
  | "not T = F"
  | "not F = T"
  | "not p = NOT p"

lemma not: "Ifm bbs bs (not p) = Ifm bbs bs (NOT p)"
  by (cases p) auto

lemma not_qf: "qfree p \ qfree (not p)"
  by (cases p) auto

lemma not_bn: "bound0 p \ bound0 (not p)"
  by (cases p) auto

definition conj :: "fm \ fm \ fm"
  where "conj p q =
    (if p = F \<or> q = F then F
     else if p = T then q
     else if q = T then p
     else And p q)"

lemma conj: "Ifm bbs bs (conj p q) = Ifm bbs bs (And p q)"
  by (cases "p = F \ q = F", simp_all add: conj_def) (cases p, simp_all)

lemma conj_qf: "qfree p \ qfree q \ qfree (conj p q)"
  using conj_def by auto

lemma conj_nb: "bound0 p \ bound0 q \ bound0 (conj p q)"
  using conj_def by auto

definition disj :: "fm \ fm \ fm"
  where "disj p q =
    (if p = T \<or> q = T then T
     else if p = F then q
     else if q = F then p
     else Or p q)"

lemma disj: "Ifm bbs bs (disj p q) = Ifm bbs bs (Or p q)"
  by (cases "p = T \ q = T", simp_all add: disj_def) (cases p, simp_all)

lemma disj_qf: "qfree p \ qfree q \ qfree (disj p q)"
  using disj_def by auto

lemma disj_nb: "bound0 p \ bound0 q \ bound0 (disj p q)"
  using disj_def by auto

definition imp :: "fm \ fm \ fm"
  where "imp p q =
    (if p = F \<or> q = T then T
     else if p = T then q
     else if q = F then not p
     else Imp p q)"

lemma imp: "Ifm bbs bs (imp p q) = Ifm bbs bs (Imp p q)"
  by (cases "p = F \ q = T", simp_all add: imp_def, cases p) (simp_all add: not)

lemma imp_qf: "qfree p \ qfree q \ qfree (imp p q)"
  using imp_def by (cases "p = F \ q = T", simp_all add: imp_def, cases p) (simp_all add: not_qf)

lemma imp_nb: "bound0 p \ bound0 q \ bound0 (imp p q)"
  using imp_def by (cases "p = F \ q = T", simp_all add: imp_def, cases p) simp_all

definition iff :: "fm \ fm \ fm"
  where "iff p q =
    (if p = q then T
     else if p = not q \<or> not p = q then F
     else if p = F then not q
     else if q = F then not p
     else if p = T then q
     else if q = T then p
     else Iff p q)"

lemma iff: "Ifm bbs bs (iff p q) = Ifm bbs bs (Iff p q)"
  by (unfold iff_def, cases "p = q", simp, cases "p = not q", simp add: not)
    (cases "not p = q", auto simp add: not)

lemma iff_qf: "qfree p \ qfree q \ qfree (iff p q)"
  by (unfold iff_def, cases "p = q", auto simp add: not_qf)

lemma iff_nb: "bound0 p \ bound0 q \ bound0 (iff p q)"
  using iff_def by (unfold iff_def, cases "p = q", auto simp add: not_bn)

fun simpfm :: "fm \ fm"
  where
    "simpfm (And p q) = conj (simpfm p) (simpfm q)"
  | "simpfm (Or p q) = disj (simpfm p) (simpfm q)"
  | "simpfm (Imp p q) = imp (simpfm p) (simpfm q)"
  | "simpfm (Iff p q) = iff (simpfm p) (simpfm q)"
  | "simpfm (NOT p) = not (simpfm p)"
  | "simpfm (Lt a) = (let a' = simpnum a in case a' of C v \ if v < 0 then T else F | _ \ Lt a')"
  | "simpfm (Le a) = (let a' = simpnum a in case a' of C v \ if v \ 0 then T else F | _ \ Le a')"
  | "simpfm (Gt a) = (let a' = simpnum a in case a' of C v \ if v > 0 then T else F | _ \ Gt a')"
  | "simpfm (Ge a) = (let a' = simpnum a in case a' of C v \ if v \ 0 then T else F | _ \ Ge a')"
  | "simpfm (Eq a) = (let a' = simpnum a in case a' of C v \ if v = 0 then T else F | _ \ Eq a')"
  | "simpfm (NEq a) = (let a' = simpnum a in case a' of C v \ if v \ 0 then T else F | _ \ NEq a')"
  | "simpfm (Dvd i a) =
      (if i = 0 then simpfm (Eq a)
       else if \<bar>i\<bar> = 1 then T
       else let a' = simpnum a in case a' of C v \<Rightarrow> if i dvd v then T else F | _ \<Rightarrow> Dvd i a')"
  | "simpfm (NDvd i a) =
      (if i = 0 then simpfm (NEq a)
       else if \<bar>i\<bar> = 1 then F
       else let a' = simpnum a in case a' of C v \<Rightarrow> if \<not>( i dvd v) then T else F | _ \<Rightarrow> NDvd i a')"
  | "simpfm p = p"

lemma simpfm: "Ifm bbs bs (simpfm p) = Ifm bbs bs p"
proof (induct p rule: simpfm.induct)
  case (6 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (7 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (8 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (9 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (10 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (11 a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
  then show ?case
  proof cases
    case 1
    with sa show ?thesis by simp
  next
    case 2
    with sa show ?thesis by (cases ?sa) (simp_all add: Let_def)
  qed
next
  case (12 i a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider "i = 0" | "\i\ = 1" | "i \ 0" "\i\ \ 1" by blast
  then show ?case
  proof cases
    case 1
    then show ?thesis
      using "12.hyps" by (simp add: dvd_def Let_def)
  next
    case 2
    with one_dvd[of "Inum bs a"] uminus_dvd_conv[where d="1" and t="Inum bs a"]
    show ?thesis
      apply (cases "i = 0")
      apply (simp_all add: Let_def)
      apply (cases "i > 0")
      apply simp_all
      done
  next
    case i: 3
    consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
    then show ?thesis
    proof cases
      case 1
      with sa[symmetric] i show ?thesis
        by (cases "\i\ = 1") auto
    next
      case 2
      then have "simpfm (Dvd i a) = Dvd i ?sa"
        using i by (cases ?sa) (auto simp add: Let_def)
      with sa show ?thesis by simp
    qed
  qed
next
  case (13 i a)
  let ?sa = "simpnum a"
  from simpnum_ci have sa: "Inum bs ?sa = Inum bs a"
    by simp
  consider "i = 0" | "\i\ = 1" | "i \ 0" "\i\ \ 1" by blast
  then show ?case
  proof cases
    case 1
    then show ?thesis
      using "13.hyps" by (simp add: dvd_def Let_def)
  next
    case 2
    with one_dvd[of "Inum bs a"] uminus_dvd_conv[where d="1" and t="Inum bs a"]
    show ?thesis
      apply (cases "i = 0")
      apply (simp_all add: Let_def)
      apply (cases "i > 0")
      apply simp_all
      done
  next
    case i: 3
    consider v where "?sa = C v" | "\ (\v. ?sa = C v)" by blast
    then show ?thesis
    proof cases
      case 1
      with sa[symmetric] i show ?thesis
        by (cases "\i\ = 1") auto
    next
      case 2
      then have "simpfm (NDvd i a) = NDvd i ?sa"
        using i by (cases ?sa) (auto simp add: Let_def)
      with sa show ?thesis by simp
    qed
  qed
qed (simp_all add: conj disj imp iff not)

lemma simpfm_bound0: "bound0 p \ bound0 (simpfm p)"
proof (induct p rule: simpfm.induct)
  case (6 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (7 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (8 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (9 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (10 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (11 a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (12 i a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
next
  case (13 i a)
  then have nb: "numbound0 a" by simp
  then have "numbound0 (simpnum a)" by (simp only: simpnum_numbound0[OF nb])
  then show ?case by (cases "simpnum a") (auto simp add: Let_def)
qed (auto simp add: disj_def imp_def iff_def conj_def not_bn)

lemma simpfm_qf: "qfree p \ qfree (simpfm p)"
  apply (induct p rule: simpfm.induct)
  apply (auto simp add: disj_qf imp_qf iff_qf conj_qf not_qf Let_def)
  apply (case_tac "simpnum a", auto)+
  done


subsection \<open>Generic quantifier elimination\<close>

fun qelim :: "fm \ (fm \ fm) \ fm"
  where
    "qelim (E p) = (\qe. DJ qe (qelim p qe))"
  | "qelim (A p) = (\qe. not (qe ((qelim (NOT p) qe))))"
  | "qelim (NOT p) = (\qe. not (qelim p qe))"
  | "qelim (And p q) = (\qe. conj (qelim p qe) (qelim q qe))"
  | "qelim (Or p q) = (\qe. disj (qelim p qe) (qelim q qe))"
  | "qelim (Imp p q) = (\qe. imp (qelim p qe) (qelim q qe))"
  | "qelim (Iff p q) = (\qe. iff (qelim p qe) (qelim q qe))"
  | "qelim p = (\y. simpfm p)"

lemma qelim_ci:
  assumes qe_inv: "\bs p. qfree p \ qfree (qe p) \ Ifm bbs bs (qe p) = Ifm bbs bs (E p)"
  shows "\bs. qfree (qelim p qe) \ Ifm bbs bs (qelim p qe) = Ifm bbs bs p"
  using qe_inv DJ_qe[OF qe_inv]
  by (induct p rule: qelim.induct)
    (auto simp add: not disj conj iff imp not_qf disj_qf conj_qf imp_qf iff_qf
      simpfm simpfm_qf simp del: simpfm.simps)

text \<open>Linearity for fm where Bound 0 ranges over \<open>\<int>\<close>\<close>

fun zsplit0 :: "num \ int \ num" \ \splits the bounded from the unbounded part\
  where
    "zsplit0 (C c) = (0, C c)"
  | "zsplit0 (Bound n) = (if n = 0 then (1, C 0) else (0, Bound n))"
  | "zsplit0 (CN n i a) =
      (let (i', a') =  zsplit0 a
       in if n = 0 then (i + i', a') else (i', CN n i a'))"
  | "zsplit0 (Neg a) = (let (i', a') = zsplit0 a in (-i', Neg a'))"
  | "zsplit0 (Add a b) =
      (let
        (ia, a') = zsplit0 a;
        (ib, b') = zsplit0 b
       in (ia + ib, Add a' b'))"
  | "zsplit0 (Sub a b) =
      (let
        (ia, a') = zsplit0 a;
        (ib, b') = zsplit0 b
       in (ia - ib, Sub a' b'))"
  | "zsplit0 (Mul i a) = (let (i', a') = zsplit0 a in (i*i', Mul i a'))"

lemma zsplit0_I:
  "\n a. zsplit0 t = (n, a) \
    (Inum ((x::int) # bs) (CN 0 n a) = Inum (x # bs) t) \<and> numbound0 a"
  (is "\n a. ?S t = (n,a) \ (?I x (CN 0 n a) = ?I x t) \ ?N a")
proof (induct t rule: zsplit0.induct)
  case (1 c n a)
  then show ?case by auto
next
  case (2 m n a)
  then show ?case by (cases "m = 0") auto
next
  case (3 m i a n a')
  let ?j = "fst (zsplit0 a)"
  let ?b = "snd (zsplit0 a)"
  have abj: "zsplit0 a = (?j, ?b)" by simp
  show ?case
  proof (cases "m = 0")
    case False
    with 3(1)[OF abj] 3(2) show ?thesis
      by (auto simp add: Let_def split_def)
  next
    case m: True
    with abj have th: "a' = ?b \ n = i + ?j"
      using 3 by (simp add: Let_def split_def)
    from abj 3 m have th2: "(?I x (CN 0 ?j ?b) = ?I x a) \ ?N ?b"
      by blast
    from th have "?I x (CN 0 n a') = ?I x (CN 0 (i + ?j) ?b)"
      by simp
    also from th2 have "\ = ?I x (CN 0 i (CN 0 ?j ?b))"
      by (simp add: distrib_right)
    finally have "?I x (CN 0 n a') = ?I x (CN 0 i a)"
      using th2 by simp
    with th2 th m show ?thesis
      by blast
  qed
next
  case (4 t n a)
  let ?nt = "fst (zsplit0 t)"
  let ?at = "snd (zsplit0 t)"
  have abj: "zsplit0 t = (?nt, ?at)"
    by simp
  then have th: "a = Neg ?at \ n = - ?nt"
    using 4 by (simp add: Let_def split_def)
  from abj 4 have th2: "(?I x (CN 0 ?nt ?at) = ?I x t) \ ?N ?at"
    by blast
  from th2[simplified] th[simplified] show ?case
    by simp
next
  case (5 s t n a)
  let ?ns = "fst (zsplit0 s)"
  let ?as = "snd (zsplit0 s)"
  let ?nt = "fst (zsplit0 t)"
  let ?at = "snd (zsplit0 t)"
  have abjs: "zsplit0 s = (?ns, ?as)"
    by simp
  moreover have abjt: "zsplit0 t = (?nt, ?at)"
    by simp
  ultimately have th: "a = Add ?as ?at \ n = ?ns + ?nt"
    using 5 by (simp add: Let_def split_def)
  from abjs[symmetric] have bluddy: "\x y. (x, y) = zsplit0 s"
    by blast
  from 5 have "(\x y. (x, y) = zsplit0 s) \
    (\<forall>xa xb. zsplit0 t = (xa, xb) \<longrightarrow> Inum (x # bs) (CN 0 xa xb) = Inum (x # bs) t \<and> numbound0 xb)"
    by auto
  with bluddy abjt have th3: "(?I x (CN 0 ?nt ?at) = ?I x t) \ ?N ?at"
    by blast
  from abjs 5 have th2: "(?I x (CN 0 ?ns ?as) = ?I x s) \ ?N ?as"
    by blast
  from th3[simplified] th2[simplified] th[simplified] show ?case
    by (simp add: distrib_right)
next
  case (6 s t n a)
  let ?ns = "fst (zsplit0 s)"
  let ?as = "snd (zsplit0 s)"
  let ?nt = "fst (zsplit0 t)"
  let ?at = "snd (zsplit0 t)"
  have abjs: "zsplit0 s = (?ns, ?as)"
    by simp
  moreover have abjt: "zsplit0 t = (?nt, ?at)"
    by simp
  ultimately have th: "a = Sub ?as ?at \ n = ?ns - ?nt"
    using 6 by (simp add: Let_def split_def)
  from abjs[symmetric] have bluddy: "\x y. (x, y) = zsplit0 s"
    by blast
  from 6 have "(\x y. (x,y) = zsplit0 s) \
    (\<forall>xa xb. zsplit0 t = (xa, xb) \<longrightarrow> Inum (x # bs) (CN 0 xa xb) = Inum (x # bs) t \<and> numbound0 xb)"
    by auto
  with bluddy abjt have th3: "(?I x (CN 0 ?nt ?at) = ?I x t) \ ?N ?at"
    by blast
  from abjs 6 have th2: "(?I x (CN 0 ?ns ?as) = ?I x s) \ ?N ?as"
    by blast
  from th3[simplified] th2[simplified] th[simplified] show ?case
    by (simp add: left_diff_distrib)
next
  case (7 i t n a)
  let ?nt = "fst (zsplit0 t)"
  let ?at = "snd (zsplit0 t)"
  have abj: "zsplit0 t = (?nt,?at)"
    by simp
  then have th: "a = Mul i ?at \ n = i * ?nt"
    using 7 by (simp add: Let_def split_def)
  from abj 7 have th2: "(?I x (CN 0 ?nt ?at) = ?I x t) \ ?N ?at"
    by blast
  then have "?I x (Mul i t) = i * ?I x (CN 0 ?nt ?at)"
    by simp
  also have "\ = ?I x (CN 0 (i*?nt) (Mul i ?at))"
    by (simp add: distrib_left)
  finally show ?case using th th2
    by simp
qed

fun iszlfm :: "fm \ bool" \ \linearity test for fm\
  where
    "iszlfm (And p q) \ iszlfm p \ iszlfm q"
  | "iszlfm (Or p q) \ iszlfm p \ iszlfm q"
  | "iszlfm (Eq (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (NEq (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (Lt (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (Le (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (Gt (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (Ge (CN 0 c e)) \ c > 0 \ numbound0 e"
  | "iszlfm (Dvd i (CN 0 c e)) \ c > 0 \ i > 0 \ numbound0 e"
  | "iszlfm (NDvd i (CN 0 c e)) \ c > 0 \ i > 0 \ numbound0 e"
  | "iszlfm p \ isatom p \ bound0 p"

lemma zlin_qfree: "iszlfm p \ qfree p"
  by (induct p rule: iszlfm.induct) auto

fun zlfm :: "fm \ fm" \ \linearity transformation for fm\
  where
    "zlfm (And p q) = And (zlfm p) (zlfm q)"
  | "zlfm (Or p q) = Or (zlfm p) (zlfm q)"
  | "zlfm (Imp p q) = Or (zlfm (NOT p)) (zlfm q)"
  | "zlfm (Iff p q) = Or (And (zlfm p) (zlfm q)) (And (zlfm (NOT p)) (zlfm (NOT q)))"
  | "zlfm (Lt a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then Lt r else
        if c > 0 then (Lt (CN 0 c r))
        else Gt (CN 0 (- c) (Neg r)))"
  | "zlfm (Le a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then Le r
        else if c > 0 then Le (CN 0 c r)
        else Ge (CN 0 (- c) (Neg r)))"
  | "zlfm (Gt a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then Gt r else
        if c > 0 then Gt (CN 0 c r)
        else Lt (CN 0 (- c) (Neg r)))"
  | "zlfm (Ge a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then Ge r
        else if c > 0 then Ge (CN 0 c r)
        else Le (CN 0 (- c) (Neg r)))"
  | "zlfm (Eq a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then Eq r
        else if c > 0 then Eq (CN 0 c r)
        else Eq (CN 0 (- c) (Neg r)))"
  | "zlfm (NEq a) =
      (let (c, r) = zsplit0 a in
        if c = 0 then NEq r
        else if c > 0 then NEq (CN 0 c r)
        else NEq (CN 0 (- c) (Neg r)))"
  | "zlfm (Dvd i a) =
      (if i = 0 then zlfm (Eq a)
       else
        let (c, r) = zsplit0 a in
          if c = 0 then Dvd \<bar>i\<bar> r
          else if c > 0 then Dvd \<bar>i\<bar> (CN 0 c r)
          else Dvd \<bar>i\<bar> (CN 0 (- c) (Neg r)))"
  | "zlfm (NDvd i a) =
      (if i = 0 then zlfm (NEq a)
       else
        let (c, r) = zsplit0 a in
          if c = 0 then NDvd \<bar>i\<bar> r
          else if c > 0 then NDvd \<bar>i\<bar> (CN 0 c r)
          else NDvd \<bar>i\<bar> (CN 0 (- c) (Neg r)))"
  | "zlfm (NOT (And p q)) = Or (zlfm (NOT p)) (zlfm (NOT q))"
  | "zlfm (NOT (Or p q)) = And (zlfm (NOT p)) (zlfm (NOT q))"
  | "zlfm (NOT (Imp p q)) = And (zlfm p) (zlfm (NOT q))"
  | "zlfm (NOT (Iff p q)) = Or (And(zlfm p) (zlfm(NOT q))) (And (zlfm(NOT p)) (zlfm q))"
  | "zlfm (NOT (NOT p)) = zlfm p"
  | "zlfm (NOT T) = F"
  | "zlfm (NOT F) = T"
  | "zlfm (NOT (Lt a)) = zlfm (Ge a)"
  | "zlfm (NOT (Le a)) = zlfm (Gt a)"
  | "zlfm (NOT (Gt a)) = zlfm (Le a)"
  | "zlfm (NOT (Ge a)) = zlfm (Lt a)"
  | "zlfm (NOT (Eq a)) = zlfm (NEq a)"
  | "zlfm (NOT (NEq a)) = zlfm (Eq a)"
  | "zlfm (NOT (Dvd i a)) = zlfm (NDvd i a)"
  | "zlfm (NOT (NDvd i a)) = zlfm (Dvd i a)"
  | "zlfm (NOT (Closed P)) = NClosed P"
  | "zlfm (NOT (NClosed P)) = Closed P"
  | "zlfm p = p"

lemma zlfm_I:
  assumes qfp: "qfree p"
  shows "Ifm bbs (i # bs) (zlfm p) = Ifm bbs (i # bs) p \ iszlfm (zlfm p)"
    (is "?I (?l p) = ?I p \ ?L (?l p)")
  using qfp
proof (induct p rule: zlfm.induct)
  case (5 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 5 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (6 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 6 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (7 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 7 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (8 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 8 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (9 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia:"Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 9 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (10 a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  from 10 Ia nb show ?case
    apply (auto simp add: Let_def split_def algebra_simps)
    apply (cases "?r")
    apply auto
    subgoal for nat a b by (cases nat) auto
    done
next
  case (11 j a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c,?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i#bs) t"
  consider "j = 0" | "j \ 0" "?c = 0" | "j \ 0" "?c > 0" | "j \ 0" "?c < 0"
    by arith
  then show ?case
  proof cases
    case 1
    then have z: "zlfm (Dvd j a) = (zlfm (Eq a))"
      by (simp add: Let_def)
    with 11 \<open>j = 0\<close> show ?thesis
      by (simp del: zlfm.simps)
  next
    case 2
    with zsplit0_I[OF spl, where x="i" and bs="bs"show ?thesis
      apply (auto simp add: Let_def split_def algebra_simps)
      apply (cases "?r")
      apply auto
      subgoal for nat a b by (cases nat) auto
      done
  next
    case 3
    then have l: "?L (?l (Dvd j a))"
      by (simp add: nb Let_def split_def)
    with Ia 3 show ?thesis
      by (simp add: Let_def split_def)
  next
    case 4
    then have l: "?L (?l (Dvd j a))"
      by (simp add: nb Let_def split_def)
    with Ia 4 dvd_minus_iff[of "\j\" "?c*i + ?N ?r"] show ?thesis
      by (simp add: Let_def split_def)
  qed
next
  case (12 j a)
  let ?c = "fst (zsplit0 a)"
  let ?r = "snd (zsplit0 a)"
  have spl: "zsplit0 a = (?c, ?r)"
    by simp
  from zsplit0_I[OF spl, where x="i" and bs="bs"]
  have Ia: "Inum (i # bs) a = Inum (i #bs) (CN 0 ?c ?r)" and nb: "numbound0 ?r"
    by auto
  let ?N = "\t. Inum (i # bs) t"
  consider "j = 0" | "j \ 0" "?c = 0" | "j \ 0" "?c > 0" | "j \ 0" "?c < 0"
    by arith
  then show ?case
  proof cases
    case 1
    then have z: "zlfm (NDvd j a) = zlfm (NEq a)"
      by (simp add: Let_def)
    with assms 12 \<open>j = 0\<close> show ?thesis
      by (simp del: zlfm.simps)
  next
    case 2
    with zsplit0_I[OF spl, where x="i" and bs="bs"show ?thesis
      apply (auto simp add: Let_def split_def algebra_simps)
      apply (cases "?r")
      apply auto
      subgoal for nat a b by (cases nat) auto
      done
  next
    case 3
    then have l: "?L (?l (Dvd j a))"
      by (simp add: nb Let_def split_def)
    with Ia 3 show ?thesis
      by (simp add: Let_def split_def)
  next
    case 4
    then have l: "?L (?l (Dvd j a))"
      by (simp add: nb Let_def split_def)
    with Ia 4 dvd_minus_iff[of "\j\" "?c*i + ?N ?r"] show ?thesis
      by (simp add: Let_def split_def)
  qed
qed auto

fun minusinf :: "fm \ fm" \ \virtual substitution of \-\\\
  where
    "minusinf (And p q) = And (minusinf p) (minusinf q)"
  | "minusinf (Or p q) = Or (minusinf p) (minusinf q)"
  | "minusinf (Eq (CN 0 c e)) = F"
  | "minusinf (NEq (CN 0 c e)) = T"
  | "minusinf (Lt (CN 0 c e)) = T"
  | "minusinf (Le (CN 0 c e)) = T"
  | "minusinf (Gt (CN 0 c e)) = F"
  | "minusinf (Ge (CN 0 c e)) = F"
  | "minusinf p = p"

lemma minusinf_qfree: "qfree p \ qfree (minusinf p)"
  by (induct p rule: minusinf.induct) auto

fun plusinf :: "fm \ fm" \ \virtual substitution of \+\\\
  where
    "plusinf (And p q) = And (plusinf p) (plusinf q)"
  | "plusinf (Or p q) = Or (plusinf p) (plusinf q)"
  | "plusinf (Eq (CN 0 c e)) = F"
  | "plusinf (NEq (CN 0 c e)) = T"
  | "plusinf (Lt (CN 0 c e)) = F"
  | "plusinf (Le (CN 0 c e)) = F"
  | "plusinf (Gt (CN 0 c e)) = T"
  | "plusinf (Ge (CN 0 c e)) = T"
  | "plusinf p = p"

fun \<delta> :: "fm \<Rightarrow> int"  \<comment> \<open>compute \<open>lcm {d| N\<^sup>? Dvd c*x+t \<in> p}\<close>\<close>
  where
    "\ (And p q) = lcm (\ p) (\ q)"
  | "\ (Or p q) = lcm (\ p) (\ q)"
  | "\ (Dvd i (CN 0 c e)) = i"
  | "\ (NDvd i (CN 0 c e)) = i"
  | "\ p = 1"

fun d_\<delta> :: "fm \<Rightarrow> int \<Rightarrow> bool"  \<comment> \<open>check if a given \<open>l\<close> divides all the \<open>ds\<close> above\<close>
  where
    "d_\ (And p q) d \ d_\ p d \ d_\ q d"
  | "d_\ (Or p q) d \ d_\ p d \ d_\ q d"
  | "d_\ (Dvd i (CN 0 c e)) d \ i dvd d"
  | "d_\ (NDvd i (CN 0 c e)) d \ i dvd d"
  | "d_\ p d \ True"

lemma delta_mono:
  assumes lin: "iszlfm p"
    and d: "d dvd d'"
    and ad: "d_\ p d"
  shows "d_\ p d'"
  using lin ad
proof (induct p rule: iszlfm.induct)
  case (9 i c e)
  then show ?case using d
    by (simp add: dvd_trans[of "i" "d" "d'"])
next
  case (10 i c e)
  then show ?case using d
    by (simp add: dvd_trans[of "i" "d" "d'"])
qed simp_all

lemma \<delta>:
  assumes lin: "iszlfm p"
  shows "d_\ p (\ p) \ \ p >0"
  using lin
  by (induct p rule: iszlfm.induct) (auto intro: delta_mono simp add: lcm_pos_int)

fun a_\<beta> :: "fm \<Rightarrow> int \<Rightarrow> fm"  \<comment> \<open>adjust the coefficients of a formula\<close>
  where
    "a_\ (And p q) k = And (a_\ p k) (a_\ q k)"
  | "a_\ (Or p q) k = Or (a_\ p k) (a_\ q k)"
  | "a_\ (Eq (CN 0 c e)) k = Eq (CN 0 1 (Mul (k div c) e))"
  | "a_\ (NEq (CN 0 c e)) k = NEq (CN 0 1 (Mul (k div c) e))"
  | "a_\ (Lt (CN 0 c e)) k = Lt (CN 0 1 (Mul (k div c) e))"
  | "a_\ (Le (CN 0 c e)) k = Le (CN 0 1 (Mul (k div c) e))"
  | "a_\ (Gt (CN 0 c e)) k = Gt (CN 0 1 (Mul (k div c) e))"
  | "a_\ (Ge (CN 0 c e)) k = Ge (CN 0 1 (Mul (k div c) e))"
  | "a_\ (Dvd i (CN 0 c e)) k = Dvd ((k div c)*i) (CN 0 1 (Mul (k div c) e))"
  | "a_\ (NDvd i (CN 0 c e)) k = NDvd ((k div c)*i) (CN 0 1 (Mul (k div c) e))"
  | "a_\ p k = p"

fun d_\<beta> :: "fm \<Rightarrow> int \<Rightarrow> bool"  \<comment> \<open>test if all coeffs of \<open>c\<close> divide a given \<open>l\<close>\<close>
  where
    "d_\ (And p q) k \ d_\ p k \ d_\ q k"
  | "d_\ (Or p q) k \ d_\ p k \ d_\ q k"
  | "d_\ (Eq (CN 0 c e)) k \ c dvd k"
  | "d_\ (NEq (CN 0 c e)) k \ c dvd k"
  | "d_\ (Lt (CN 0 c e)) k \ c dvd k"
  | "d_\ (Le (CN 0 c e)) k \ c dvd k"
  | "d_\ (Gt (CN 0 c e)) k \ c dvd k"
  | "d_\ (Ge (CN 0 c e)) k \ c dvd k"
  | "d_\ (Dvd i (CN 0 c e)) k \ c dvd k"
  | "d_\ (NDvd i (CN 0 c e)) k \ c dvd k"
  | "d_\ p k \ True"

fun \<zeta> :: "fm \<Rightarrow> int"  \<comment> \<open>computes the lcm of all coefficients of \<open>x\<close>\<close>
  where
    "\ (And p q) = lcm (\ p) (\ q)"
  | "\ (Or p q) = lcm (\ p) (\ q)"
  | "\ (Eq (CN 0 c e)) = c"
  | "\ (NEq (CN 0 c e)) = c"
  | "\ (Lt (CN 0 c e)) = c"
  | "\ (Le (CN 0 c e)) = c"
  | "\ (Gt (CN 0 c e)) = c"
  | "\ (Ge (CN 0 c e)) = c"
  | "\ (Dvd i (CN 0 c e)) = c"
  | "\ (NDvd i (CN 0 c e))= c"
  | "\ p = 1"

fun \<beta> :: "fm \<Rightarrow> num list"
  where
    "\ (And p q) = (\ p @ \ q)"
  | "\ (Or p q) = (\ p @ \ q)"
  | "\ (Eq (CN 0 c e)) = [Sub (C (- 1)) e]"
  | "\ (NEq (CN 0 c e)) = [Neg e]"
  | "\ (Lt (CN 0 c e)) = []"
  | "\ (Le (CN 0 c e)) = []"
  | "\ (Gt (CN 0 c e)) = [Neg e]"
  | "\ (Ge (CN 0 c e)) = [Sub (C (- 1)) e]"
  | "\ p = []"

fun \<alpha> :: "fm \<Rightarrow> num list"
  where
    "\ (And p q) = \ p @ \ q"
  | "\ (Or p q) = \ p @ \ q"
  | "\ (Eq (CN 0 c e)) = [Add (C (- 1)) e]"
  | "\ (NEq (CN 0 c e)) = [e]"
  | "\ (Lt (CN 0 c e)) = [e]"
  | "\ (Le (CN 0 c e)) = [Add (C (- 1)) e]"
  | "\ (Gt (CN 0 c e)) = []"
  | "\ (Ge (CN 0 c e)) = []"
  | "\ p = []"

fun mirror :: "fm \ fm"
  where
    "mirror (And p q) = And (mirror p) (mirror q)"
  | "mirror (Or p q) = Or (mirror p) (mirror q)"
  | "mirror (Eq (CN 0 c e)) = Eq (CN 0 c (Neg e))"
  | "mirror (NEq (CN 0 c e)) = NEq (CN 0 c (Neg e))"
  | "mirror (Lt (CN 0 c e)) = Gt (CN 0 c (Neg e))"
  | "mirror (Le (CN 0 c e)) = Ge (CN 0 c (Neg e))"
  | "mirror (Gt (CN 0 c e)) = Lt (CN 0 c (Neg e))"
  | "mirror (Ge (CN 0 c e)) = Le (CN 0 c (Neg e))"
  | "mirror (Dvd i (CN 0 c e)) = Dvd i (CN 0 c (Neg e))"
  | "mirror (NDvd i (CN 0 c e)) = NDvd i (CN 0 c (Neg e))"
  | "mirror p = p"

text \<open>Lemmas for the correctness of \<open>\<sigma>_\<rho>\<close>\<close>

lemma dvd1_eq1: "x > 0 \ x dvd 1 \ x = 1"
  for x :: int
  by simp

lemma minusinf_inf:
  assumes linp: "iszlfm p"
    and u: "d_\ p 1"
  shows "\z::int. \x < z. Ifm bbs (x # bs) (minusinf p) = Ifm bbs (x # bs) p"
  (is "?P p" is "\(z::int). \x < z. ?I x (?M p) = ?I x p")
  using linp u
proof (induct p rule: minusinf.induct)
  case (1 p q)
  then show ?case
    apply auto
    subgoal for z z' by (rule exI [where x = "min z z'"]) simp
    done
next
  case (2 p q)
  then show ?case
    apply auto
    subgoal for z z' by (rule exI [where x = "min z z'"]) simp
    done
next
  case (3 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 3 have "\x<(- Inum (a # bs) e). c * x + Inum (x # bs) e \ 0"
  proof clarsimp
    fix x
    assume "x < (- Inum (a # bs) e)" and "x + Inum (x # bs) e = 0"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show False by simp
  qed
  then show ?case by auto
next
  case (4 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 4 have "\x < (- Inum (a # bs) e). c * x + Inum (x # bs) e \ 0"
  proof clarsimp
    fix x
    assume "x < (- Inum (a # bs) e)" and "x + Inum (x # bs) e = 0"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show "False" by simp
  qed
  then show ?case by auto
next
  case (5 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 5 have "\x<(- Inum (a # bs) e). c * x + Inum (x # bs) e < 0"
  proof clarsimp
    fix x
    assume "x < (- Inum (a # bs) e)"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show "x + Inum (x # bs) e < 0"
      by simp
  qed
  then show ?case by auto
next
  case (6 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 6 have "\x<(- Inum (a # bs) e). c * x + Inum (x # bs) e \ 0"
  proof clarsimp
    fix x
    assume "x < (- Inum (a # bs) e)"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show "x + Inum (x # bs) e \ 0" by simp
  qed
  then show ?case by auto
next
  case (7 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 7 have "\x<(- Inum (a # bs) e). \ (c * x + Inum (x # bs) e > 0)"
  proof clarsimp
    fix x
    assume "x < - Inum (a # bs) e" and "x + Inum (x # bs) e > 0"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show False by simp
  qed
  then show ?case by auto
next
  case (8 c e)
  then have c1: "c = 1" and nb: "numbound0 e"
    by simp_all
  fix a
  from 8 have "\x<(- Inum (a # bs) e). \ c * x + Inum (x # bs) e \ 0"
  proof clarsimp
    fix x
    assume "x < (- Inum (a # bs) e)" and "x + Inum (x # bs) e \ 0"
    with numbound0_I[OF nb, where bs="bs" and b="a" and b'="x"]
    show False by simp
  qed
  then show ?case by auto
qed auto

lemma minusinf_repeats:
  assumes d: "d_\ p d"
    and linp: "iszlfm p"
  shows "Ifm bbs ((x - k * d) # bs) (minusinf p) = Ifm bbs (x # bs) (minusinf p)"
  using linp d
proof (induct p rule: iszlfm.induct)
  case (9 i c e)
  then have nbe: "numbound0 e" and id: "i dvd d"
    by simp_all
  then have "\k. d = i * k"
    by (simp add: dvd_def)
  then obtain "di" where di_def: "d = i * di"
    by blast
  show ?case
  proof (simp add: numbound0_I[OF nbe,where bs="bs" and b="x - k * d" and b'="x"] right_diff_distrib,
      rule iffI)
    assume "i dvd c * x - c * (k * d) + Inum (x # bs) e"
      (is "?ri dvd ?rc * ?rx - ?rc * (?rk * ?rd) + ?I x e" is "?ri dvd ?rt")
    then have "\l::int. ?rt = i * l"
      by (simp add: dvd_def)
    then have "\l::int. c * x + ?I x e = i * l + c * (k * i * di)"
      by (simp add: algebra_simps di_def)
    then have "\l::int. c * x + ?I x e = i* (l + c * k * di)"
      by (simp add: algebra_simps)
    then have "\l::int. c * x + ?I x e = i * l"
      by blast
    then show "i dvd c * x + Inum (x # bs) e"
      by (simp add: dvd_def)
  next
    assume "i dvd c * x + Inum (x # bs) e"  (is "?ri dvd ?rc * ?rx + ?e")
    then have "\l::int. c * x + ?e = i * l"
      by (simp add: dvd_def)
    then have "\l::int. c * x - c * (k * d) + ?e = i * l - c * (k * d)"
      by simp
    then have "\l::int. c * x - c * (k * d) + ?e = i * l - c * (k * i * di)"
      by (simp add: di_def)
    then have "\l::int. c * x - c * (k * d) + ?e = i * (l - c * k * di)"
      by (simp add: algebra_simps)
    then have "\l::int. c * x - c * (k * d) + ?e = i * l"
      by blast
    then show "i dvd c * x - c * (k * d) + Inum (x # bs) e"
      by (simp add: dvd_def)
  qed
next
  case (10 i c e)
  then have nbe: "numbound0 e" and id: "i dvd d"
    by simp_all
  then have "\k. d = i * k"
    by (simp add: dvd_def)
  then obtain di where di_def: "d = i * di"
    by blast
  show ?case
  proof (simp add: numbound0_I[OF nbe,where bs="bs" and b="x - k * d" and b'="x"] right_diff_distrib,
      rule iffI)
    assume "i dvd c * x - c * (k * d) + Inum (x # bs) e"
      (is "?ri dvd ?rc * ?rx - ?rc * (?rk * ?rd) + ?I x e" is "?ri dvd ?rt")
    then have "\l::int. ?rt = i * l"
      by (simp add: dvd_def)
    then have "\l::int. c * x + ?I x e = i * l + c * (k * i * di)"
      by (simp add: algebra_simps di_def)
    then have "\l::int. c * x+ ?I x e = i * (l + c * k * di)"
      by (simp add: algebra_simps)
    then have "\l::int. c * x + ?I x e = i * l"
      by blast
    then show "i dvd c * x + Inum (x # bs) e"
      by (simp add: dvd_def)
  next
    assume "i dvd c * x + Inum (x # bs) e" (is "?ri dvd ?rc * ?rx + ?e")
    then have "\l::int. c * x + ?e = i * l"
      by (simp add: dvd_def)
    then have "\l::int. c * x - c * (k * d) + ?e = i * l - c * (k * d)"
      by simp
    then have "\l::int. c * x - c * (k * d) + ?e = i * l - c * (k * i * di)"
      by (simp add: di_def)
    then have "\l::int. c * x - c * (k * d) + ?e = i * (l - c * k * di)"
      by (simp add: algebra_simps)
    then have "\l::int. c * x - c * (k * d) + ?e = i * l"
      by blast
    then show "i dvd c * x - c * (k * d) + Inum (x # bs) e"
      by (simp add: dvd_def)
  qed
qed (auto simp add: gr0_conv_Suc numbound0_I[where bs="bs" and b="x - k*d" and b'="x"])

lemma mirror_\<alpha>_\<beta>:
  assumes lp: "iszlfm p"
  shows "Inum (i # bs) ` set (\ p) = Inum (i # bs) ` set (\ (mirror p))"
  using lp by (induct p rule: mirror.induct) auto

lemma mirror:
  assumes lp: "iszlfm p"
  shows "Ifm bbs (x # bs) (mirror p) = Ifm bbs ((- x) # bs) p"
  using lp
proof (induct p rule: iszlfm.induct)
  case (9 j c e)
  then have nb: "numbound0 e"
    by simp
  have "Ifm bbs (x # bs) (mirror (Dvd j (CN 0 c e))) \ j dvd c * x - Inum (x # bs) e"
    (is "_ = (j dvd c*x - ?e)"by simp
  also have "\ \ j dvd (- (c * x - ?e))"
    by (simp only: dvd_minus_iff)
  also have "\ \ j dvd (c * (- x)) + ?e"
    by (simp only: minus_mult_right[symmetric] minus_mult_left[symmetric] ac_simps minus_add_distrib)
      (simp add: algebra_simps)
  also have "\ = Ifm bbs ((- x) # bs) (Dvd j (CN 0 c e))"
    using numbound0_I[OF nb, where bs="bs" and b="x" and b'="- x"] by simp
  finally show ?case .
next
  case (10 j c e)
  then have nb: "numbound0 e"
    by simp
  have "Ifm bbs (x # bs) (mirror (Dvd j (CN 0 c e))) \ j dvd c * x - Inum (x # bs) e"
    (is "_ = (j dvd c * x - ?e)"by simp
  also have "\ \ j dvd (- (c * x - ?e))"
    by (simp only: dvd_minus_iff)
  also have "\ \ j dvd (c * (- x)) + ?e"
    by (simp only: minus_mult_right[symmetric] minus_mult_left[symmetric] ac_simps minus_add_distrib)
      (simp add: algebra_simps)
  also have "\ \ Ifm bbs ((- x) # bs) (Dvd j (CN 0 c e))"
    using numbound0_I[OF nb, where bs="bs" and b="x" and b'="- x"] by simp
  finally show ?case by simp
qed (auto simp add: numbound0_I[where bs="bs" and b="x" and b'="- x"] gr0_conv_Suc)

lemma mirror_l: "iszlfm p \ d_\ p 1 \ iszlfm (mirror p) \ d_\ (mirror p) 1"
  by (induct p rule: mirror.induct) auto

lemma mirror_\<delta>: "iszlfm p \<Longrightarrow> \<delta> (mirror p) = \<delta> p"
  by (induct p rule: mirror.induct) auto

lemma \<beta>_numbound0:
  assumes lp: "iszlfm p"
  shows "\b \ set (\ p). numbound0 b"
  using lp by (induct p rule: \<beta>.induct) auto

lemma d_\<beta>_mono:
  assumes linp: "iszlfm p"
    and dr: "d_\ p l"
    and d: "l dvd l'"
  shows "d_\ p l'"
  using dr linp dvd_trans[of _ "l" "l'", simplified d]
  by (induct p rule: iszlfm.induct) simp_all

lemma \<alpha>_l:
  assumes "iszlfm p"
  shows "\b \ set (\ p). numbound0 b"
  using assms by (induct p rule: \<alpha>.induct) auto

lemma \<zeta>:
  assumes "iszlfm p"
  shows "\ p > 0 \ d_\ p (\ p)"
  using assms
proof (induct p rule: iszlfm.induct)
  case (1 p q)
  from 1 have dl1: "\ p dvd lcm (\ p) (\ q)"
    by simp
  from 1 have dl2: "\ q dvd lcm (\ p) (\ q)"
    by simp
  from 1 d_\<beta>_mono[where p = "p" and l="\<zeta> p" and l'="lcm (\<zeta> p) (\<zeta> q)"]
      d_\<beta>_mono[where p = "q" and l="\<zeta> q" and l'="lcm (\<zeta> p) (\<zeta> q)"]
      dl1 dl2
  show ?case
    by (auto simp add: lcm_pos_int)
next
  case (2 p q)
  from 2 have dl1: "\ p dvd lcm (\ p) (\ q)"
    by simp
  from 2 have dl2: "\ q dvd lcm (\ p) (\ q)"
    by simp
  from 2 d_\<beta>_mono[where p = "p" and l="\<zeta> p" and l'="lcm (\<zeta> p) (\<zeta> q)"]
      d_\<beta>_mono[where p = "q" and l="\<zeta> q" and l'="lcm (\<zeta> p) (\<zeta> q)"]
      dl1 dl2
  show ?case
    by (auto simp add: lcm_pos_int)
qed (auto simp add: lcm_pos_int)

lemma a_\<beta>:
  assumes linp: "iszlfm p"
    and d: "d_\ p l"
    and lp: "l > 0"
  shows "iszlfm (a_\ p l) \ d_\ (a_\ p l) 1 \ Ifm bbs (l * x # bs) (a_\ p l) = Ifm bbs (x # bs) p"
  using linp d
proof (induct p rule: iszlfm.induct)
  case (5 c e)
  then have cp: "c > 0" and be: "numbound0 e" and d': "c dvd l"
    by simp_all
  from lp cp have clel: "c \ l"
    by (simp add: zdvd_imp_le [OF d' lp])
  from cp have cnz: "c \ 0"
    by simp
  have "c div c \ l div c"
    by (simp add: zdiv_mono1[OF clel cp])
  then have ldcp: "0 < l div c"
    by (simp add: div_self[OF cnz])
  have "c * (l div c) = c * (l div c) + l mod c"
    using d' dvd_eq_mod_eq_0[of "c" "l"] by simp
  then have cl: "c * (l div c) =l"
    using mult_div_mod_eq [where a="l" and b="c"by simp
  then have "(l * x + (l div c) * Inum (x # bs) e < 0) \
      ((c * (l div c)) * x + (l div c) * Inum (x # bs) e < 0)"
    by simp
  also have "\ \ (l div c) * (c * x + Inum (x # bs) e) < (l div c) * 0"
    by (simp add: algebra_simps)
  also have "\ \ c * x + Inum (x # bs) e < 0"
    using mult_less_0_iff [where a="(l div c)" and b="c*x + Inum (x # bs) e"] ldcp
    by simp
  finally show ?case
    using numbound0_I[OF be,where b="l*x" and b'="x" and bs="bs"] be
    by simp
next
  case (6 c e)
  then have cp: "c > 0" and be: "numbound0 e" and d': "c dvd l"
    by simp_all
  from lp cp have clel: "c \ l"
    by (simp add: zdvd_imp_le [OF d' lp])
  from cp have cnz: "c \ 0"
    by simp
  have "c div c \ l div c"
    by (simp add: zdiv_mono1[OF clel cp])
  then have ldcp:"0 < l div c"
    by (simp add: div_self[OF cnz])
  have "c * (l div c) = c * (l div c) + l mod c"
    using d' dvd_eq_mod_eq_0[of "c" "l"] by simp
  then have cl: "c * (l div c) = l"
    using mult_div_mod_eq [where a="l" and b="c"by simp
  then have "l * x + (l div c) * Inum (x # bs) e \ 0 \
      (c * (l div c)) * x + (l div c) * Inum (x # bs) e \<le> 0"
    by simp
  also have "\ \ (l div c) * (c * x + Inum (x # bs) e) \ (l div c) * 0"
    by (simp add: algebra_simps)
  also have "\ \ c * x + Inum (x # bs) e \ 0"
    using mult_le_0_iff [where a="(l div c)" and b="c*x + Inum (x # bs) e"] ldcp by simp
  finally show ?case
    using numbound0_I[OF be,where b="l*x" and b'="x" and bs="bs"] be by simp
next
  case (7 c e)
  then have cp: "c > 0" and be: "numbound0 e" and d': "c dvd l"
    by simp_all
  from lp cp have clel: "c \ l"
    by (simp add: zdvd_imp_le [OF d' lp])
  from cp have cnz: "c \ 0"
    by simp
  have "c div c \ l div c"
    by (simp add: zdiv_mono1[OF clel cp])
  then have ldcp: "0 < l div c"
    by (simp add: div_self[OF cnz])
  have "c * (l div c) = c * (l div c) + l mod c"
    using d' dvd_eq_mod_eq_0[of "c" "l"] by simp
  then have cl: "c * (l div c) = l"
    using mult_div_mod_eq [where a="l" and b="c"by simp
  then have "l * x + (l div c) * Inum (x # bs) e > 0 \
      (c * (l div c)) * x + (l div c) * Inum (x # bs) e > 0"
    by simp
  also have "\ \ (l div c) * (c * x + Inum (x # bs) e) > (l div c) * 0"
    by (simp add: algebra_simps)
  also have "\ \ c * x + Inum (x # bs) e > 0"
    using zero_less_mult_iff [where a="(l div c)" and b="c * x + Inum (x # bs) e"] ldcp
    by simp
  finally show ?case
    using numbound0_I[OF be,where b="(l * x)" and b'="x" and bs="bs"] be
    by simp
next
  case (8 c e)
  then have cp: "c > 0" and be: "numbound0 e" and d': "c dvd l"
    by simp_all
  from lp cp have clel: "c \ l"
    by (simp add: zdvd_imp_le [OF d' lp])
  from cp have cnz: "c \ 0"
    by simp
  have "c div c \ l div c"
    by (simp add: zdiv_mono1[OF clel cp])
  then have ldcp: "0 < l div c"
    by (simp add: div_self[OF cnz])
  have "c * (l div c) = c * (l div c) + l mod c"
    using d' dvd_eq_mod_eq_0[of "c" "l"] by simp
  then have cl: "c * (l div c) =l"
    using mult_div_mod_eq [where a="l" and b="c"]
    by simp
--> --------------------

--> maximum size reached

--> --------------------

¤ Dauer der Verarbeitung: 0.83 Sekunden  (vorverarbeitet)  ¤





Download des
Quellennavigators
Download des
sprechenden Kalenders

in der Quellcodebibliothek suchen




Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.


Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.


Bot Zugriff