Theory QEdlo

(*  Author:     Tobias Nipkow, 2007  *)

theory QEdlo
imports DLO
begin

subsection "DNF-based quantifier elimination"

definition qe_dlo1 :: "atom list  atom fm" where
"qe_dlo1 as =
 (if Less 0 0  set as then FalseF else
  let lbs = [i. Less (Suc i) 0  as]; ubs = [j. Less 0 (Suc j)  as];
      pairs = [Atom(Less i j). i  lbs, j  ubs]
  in list_conj pairs)"

theorem I_qe_dlo1:
assumes less: "a  set as. is_Less a" and dep: "a  set as. dependsdlo a"
shows "DLO.I (qe_dlo1 as) xs = (x. a  set as. Idlo a (x#xs))"
  (is "?L = ?R")
proof
  let ?lbs = "[i. Less (Suc i) 0  as]"
  let ?ubs = "[j. Less 0 (Suc j)  as]"
  let ?Ls = "set ?lbs" let ?Us = "set ?ubs"
  let ?lb = "Max (x?Ls. {xs!x})"
  let ?ub = "Min (x?Us. {xs!x})"
  have 2: "Less 0 0  set as  a  set as.
      (i  ?Ls. a = Less (Suc i) 0)  (i  ?Us. a = Less 0 (Suc i))"
  proof
    fix a assume "Less 0 0  set as" "a  set as"
    then obtain i j where [simp]: "a = Less i j"
      using less by (force simp:is_Less_iff)
    with dep obtain k where "i = 0  j = Suc k  i = Suc k  j = 0"
      using Less 0 0  set as a  set as
      by auto (metis Nat.nat.nchotomy dependsdlo.simps(2))
    moreover hence "i=0  k  ?Us  j=0  k  ?Ls"
      using a  set as by force
    ultimately show "(i?Ls. a=Less (Suc i) 0)  (i?Us. a=Less 0 (Suc i))"
      by force
  qed
  assume qe1: ?L
  hence 0: "Less 0 0  set as" by (auto simp:qe_dlo1_def)
  with qe1 have 1: "x?Ls. y?Us. xs ! x < xs ! y"
    by (fastforce simp:qe_dlo1_def)
  have finite: "finite ?Ls" "finite ?Us" by (rule finite_set)+
  { fix i x
    assume "Less i 0  set as | Less 0 i  set as"
    moreover hence "i  0" using 0 by iprover
    ultimately have "(x#xs) ! i = xs!(i - 1)" by (simp add: nth_Cons')
  } note this[simp]
  { assume nonempty: "?Ls  {}  ?Us  {}"
    hence "Max (x?Ls. {xs!x}) < Min (x?Us. {xs!x})"
      using 1 finite by auto
    then obtain m where "?lb < m  m < ?ub" using dense by blast
    hence "i?Ls. xs!i < m" and "j?Us. m < xs!j"
      using nonempty finite by auto
    hence "a  set as. Idlo a (m # xs)" using 2[OF 0] by(auto simp:less)
    hence ?R .. }
  moreover
  { assume asm: "?Ls  {}  ?Us = {}"
    then obtain m where "?lb < m" using no_ub by blast
    hence "a set as. Idlo a (m # xs)" using 2[OF 0] asm finite by auto
    hence ?R .. }
  moreover
  { assume asm: "?Ls = {}  ?Us  {}"
    then obtain m where "m < ?ub" using no_lb by blast
    hence "a set as. Idlo a (m # xs)" using 2[OF 0] asm finite by auto
    hence ?R .. }
  moreover
  { assume "?Ls = {}  ?Us = {}"
    hence ?R using 2[OF 0] by (auto simp add:less)
  }
  ultimately show ?R by blast
next
  assume ?R
  then obtain x where 1: "a set as. Idlo a (x # xs)" ..
  hence 0: "Less 0 0  set as" by auto
  { fix i j
    assume asm: "Less i 0  set as" "Less 0 j  set as"
    hence "(x#xs)!i < x" "x < (x#xs)!j" using 1 by auto+
    hence "(x#xs)!i < (x#xs)!j" by(rule order_less_trans)
    moreover have "¬(i = 0 | j = 0)" using 0 asm by blast
    ultimately have "xs ! (i - 1) < xs ! (j - 1)" by (simp add: nth_Cons')
  }
  thus ?L using 0 less
    by (fastforce simp: qe_dlo1_def is_Less_iff split:atom.splits nat.splits)
qed

lemma I_qe_dlo1_pretty:
  "a  set as. is_Less a  dependsdlo a  DLO.is_dnf_qe _ qe_dlo1 as"
by(metis I_qe_dlo1)

definition subst :: "nat  nat  nat  nat" where
"subst i j k = (if k=0 then if i=0 then j else i else k) - 1"
fun subst0 :: "atom  atom  atom" where
"subst0 (Eq i j) a = (case a of
   Less m n  Less (subst i j m) (subst i j n)
 | Eq m n  Eq (subst i j m) (subst i j n))"

lemma subst0_pretty:
  "subst0 (Eq i j) (Less m n) = Less (subst i j m) (subst i j n)"
  "subst0 (Eq i j) (Eq m n) = Eq (subst i j m) (subst i j n)"
by auto

(*<*)
(* needed for code generation *)
definition [code del]: "lift_dnfeq_qe = ATOM_EQ.lift_dnfeq_qe negdlo dependsdlo decrdlo (λEq i j  i=0  j=0 | a  False)
          (λEq i j  i=j | a  False) subst0"
definition [code del]:
  "lift_eq_qe = ATOM_EQ.lift_eq_qe (λEq i j  i=0  j=0 | a  False)
                                   (λEq i j  i=j | a  False) subst0"

lemmas DLOe_code_lemmas = DLO_code_lemmas lift_dnfeq_qe_def lift_eq_qe_def

hide_const lift_dnfeq_qe lift_eq_qe
(*>*)

interpretation DLOe:
  ATOM_EQ negdlo "(λa. True)" Idlo dependsdlo decrdlo
          "(λEq i j  i=0  j=0 | a  False)"
          "(λEq i j  i=j | a  False)" subst0
apply(unfold_locales)
apply(fastforce simp:subst_def nth_Cons' split:atom.splits if_split_asm)
apply(simp add:subst_def split:atom.splits)
apply(fastforce simp:subst_def nth_Cons' split:atom.splits)
apply(fastforce simp add:subst_def split:atom.splits)
done

(*<*)
lemmas [folded DLOe_code_lemmas, code] =
  DLOe.lift_dnfeq_qe_def DLOe.lift_eq_qe_def
(*>*)

setup Sign.revert_abbrev "" @{const_abbrev DLOe.lift_dnfeq_qe}

definition "qe_dlo = DLOe.lift_dnfeq_qe qe_dlo1"
(*<*)
lemmas [folded DLOe_code_lemmas, code] = qe_dlo_def 
(*>*)

lemma qfree_qe_dlo1: "qfree (qe_dlo1 as)"
by(auto simp:qe_dlo1_def intro!:qfree_list_conj)

theorem I_qe_dlo: "DLO.I (qe_dlo φ) xs = DLO.I φ xs"
unfolding qe_dlo_def
by(fastforce intro!: I_qe_dlo1 qfree_qe_dlo1 DLOe.I_lift_dnfeq_qe
        simp: is_Less_iff not_is_Eq_iff split:atom.splits cong:conj_cong)

theorem qfree_qe_dlo: "qfree (qe_dlo φ)"
by(simp add:qe_dlo_def DLOe.qfree_lift_dnfeq_qe qfree_qe_dlo1)

end