Theory QElin
theory QElin
imports LinArith
begin
subsection‹Fourier›
definition qe_FM⇩1 :: "atom list ⇒ atom fm" where
"qe_FM⇩1 as = list_conj [Atom(combine p q). p←lbounds as, q←ubounds as]"
theorem I_qe_FM⇩1:
assumes less: "∀a ∈ set as. is_Less a" and dep: "∀a ∈ set as. depends⇩R a"
shows "R.I (qe_FM⇩1 as) xs = (∃x. ∀a ∈ set as. I⇩R a (x#xs))"  (is "?L = ?R")
proof
  let ?Ls = "set(lbounds as)" let ?Us = "set(ubounds as)"
  let ?lbs = "UN (r,cs):?Ls. {r + ⟨cs,xs⟩}"
  let ?ubs = "UN (r,cs):?Us. {r + ⟨cs,xs⟩}"
  have fins: "finite ?lbs ∧ finite ?ubs" by auto
  have 2: "∀f∈ set as. ∃r c cs. f = Less r (c#cs) ∧
          (c>0 ∧ (r/c,(-1/c)*⇩s cs) ∈ ?Ls ∨ c<0 ∧ (r/c,(-1/c)*⇩s cs) ∈ ?Us)"
    using dep less
    by(fastforce simp:set_lbounds set_ubounds is_Less_iff depends⇩R_def
                split:list.splits)
  assume ?L
  have 1: "∀x∈?lbs. ∀y∈?ubs. x < y"
  proof (rule ballI)+
    fix x y assume "x∈?lbs" "y∈?ubs"
    then obtain r cs
      where "(r,cs) ∈ ?Ls ∧ x = r + ⟨cs,xs⟩" by fastforce
    moreover from ‹y∈?ubs› obtain s ds
      where "(s,ds) ∈ ?Us ∧ y = s + ⟨ds,xs⟩" by fastforce
    ultimately show "x<y" using ‹?L›
      by(fastforce simp:qe_FM⇩1_def algebra_simps iprod_left_diff_distrib)
  qed
  { assume nonempty: "?lbs ≠ {} ∧ ?ubs ≠ {}"
    hence "Max ?lbs < Min ?ubs" using fins 1
      by(blast intro: Max_less_iff[THEN iffD2] Min_gr_iff[THEN iffD2])
    then obtain m where "Max ?lbs < m ∧ m < Min ?ubs"
      using dense[where 'a = real] by blast
    hence "∀a ∈ set as. I⇩R a (m#xs)" using 2 nonempty
      apply (auto simp: Ball_def)
      apply (auto simp: Bex_def)
      apply (fastforce simp: field_simps)
      done
    hence ?R .. }
  moreover
  { assume asm: "?lbs ≠ {} ∧ ?ubs = {}"
    have "∀a ∈ set as. I⇩R a ((Max ?lbs + 1) # xs)"
    proof
      fix a assume "a ∈ set as"
      then obtain r c cs
        where "a = Less r (c#cs)" "c>0" "(r/c,(-1/c)*⇩s cs) ∈ ?Ls"
        using asm 2 
          by (fastforce simp: field_simps)
      moreover hence "(r - ⟨cs,xs⟩)/c ≤ Max ?lbs"
        using asm fins
        by(auto intro!: Max_ge_iff[THEN iffD2])
          (force simp add:field_simps)
      ultimately show "I⇩R a ((Max ?lbs + 1) # xs)" by (simp add: field_simps)
    qed
    hence ?R .. }
  moreover
  { assume asm: "?lbs = {} ∧ ?ubs ≠ {}"
    have "∀a ∈ set as. I⇩R a ((Min ?ubs - 1) # xs)"
    proof
      fix a assume "a ∈ set as"
      then obtain r c cs
        where "a = Less r (c#cs)" "c<0" "(r/c,(-1/c)*⇩s cs) ∈ ?Us"
        using asm 2 by fastforce
      moreover hence "Min ?ubs ≤ (r - ⟨cs,xs⟩)/c"
        using asm fins
        by(auto intro!: Min_le_iff[THEN iffD2])
          (force simp add:field_simps)
      ultimately show "I⇩R a ((Min ?ubs - 1) # xs)" by (simp add: field_simps)
    qed
    hence ?R .. }
  moreover
  { assume "?lbs = {} ∧ ?ubs = {}"
    hence ?R using 2 less by auto (rule, fast)
  }
  ultimately show ?R by blast
next
  let ?Ls = "set(lbounds as)" let ?Us = "set(ubounds as)"
  assume ?R
  then obtain x where 1: "∀a∈ set as. I⇩R a (x#xs)" ..
  { fix r c cs s d ds
    assume "Less r (c#cs) ∈ set as" "0 < c" "Less s (d#ds) ∈ set as" "d < 0"
    hence "r < c*x + ⟨cs,xs⟩" "s < d*x + ⟨ds,xs⟩" "c > 0" "d < 0"
      using 1 by auto
    hence "(r - ⟨cs,xs⟩)/c < x" "x < (s - ⟨ds,xs⟩)/d" by(simp add:field_simps)+
    hence "(r - ⟨cs,xs⟩)/c < (s - ⟨ds,xs⟩)/d" by arith
  }
  thus ?L by (auto simp: qe_FM⇩1_def iprod_left_diff_distrib less field_simps set_lbounds set_ubounds)
qed
corollary I_qe_FM⇩1_pretty:
  "∀a ∈ set as. is_Less a ∧ depends⇩R a ⟹ R.is_dnf_qe qe_FM⇩1 as"
by(metis I_qe_FM⇩1)
fun subst⇩0 :: "atom ⇒ atom ⇒ atom" where
"subst⇩0 (Eq r (c#cs)) a = (case a of
   Less s (d#ds) ⇒ Less (s - (r*d)/c) (ds - (d/c) *⇩s cs)
 | Eq s (d#ds) ⇒ Eq (s - (r*d)/c) (ds - (d/c) *⇩s cs))"
lemma subst⇩0_pretty:
 "subst⇩0 (Eq r (c#cs)) (Less s (d#ds)) = Less (s - (r*d)/c) (ds - (d/c) *⇩s cs)"
 "subst⇩0 (Eq r (c#cs)) (Eq s (d#ds)) = Eq (s - (r*d)/c) (ds - (d/c) *⇩s cs)"
by auto
lemma I_subst⇩0: "depends⇩R a ⟹ c ≠ 0 ⟹
       I⇩R (subst⇩0 (Eq r (c#cs)) a) xs = I⇩R a ((r - ⟨cs,xs⟩)/c # xs)"
apply(cases a)
by (auto simp add: depends⇩R_def iprod_left_diff_distrib algebra_simps diff_divide_distrib split:list.splits)
interpretation R⇩e:
  ATOM_EQ neg⇩R "(λa. True)" I⇩R depends⇩R decr⇩R
          "(λEq _ (c#_) ⇒ c ≠ 0 | _ ⇒ False)"
          "(λEq r cs ⇒ r=0 ∧ (∀c∈ set cs. c=0) | _ ⇒ False)" subst⇩0
apply(unfold_locales)
   apply(simp del:subst⇩0.simps add:I_subst⇩0 split:atom.splits list.splits)
  apply(simp add: iprod0_if_coeffs0 split:atom.splits)
 apply(simp split:atom.splits list.splits)
 apply(rename_tac r ds c cs)
 apply(rule_tac x= "(r - ⟨cs,xs⟩)/c" in exI)
 apply (simp add: algebra_simps diff_divide_distrib)
apply(simp add: self_list_diff set_replicate_conv_if
        split:atom.splits list.splits)
done
definition "qe_FM = R⇩e.lift_dnfeq_qe qe_FM⇩1"
lemma qfree_qe_FM⇩1: "qfree (qe_FM⇩1 as)"
by(auto simp:qe_FM⇩1_def intro!:qfree_list_conj)
corollary I_qe_FM: "R.I (qe_FM φ) xs = R.I φ xs"
unfolding qe_FM_def
apply(rule R⇩e.I_lift_dnfeq_qe)
 apply(rule qfree_qe_FM⇩1)
apply(rule allI)
apply(rule I_qe_FM⇩1)
 prefer 2 apply blast
apply(clarify)
apply(drule_tac x=a in bspec) apply simp
apply(simp add: depends⇩R_def split:atom.splits list.splits)
done
theorem qfree_qe_FM: "qfree (qe_FM f)"
by(simp add:qe_FM_def R⇩e.qfree_lift_dnfeq_qe qfree_qe_FM⇩1)
subsubsection‹Tests›
lemmas qesimps = qe_FM_def R⇩e.lift_dnfeq_qe_def R⇩e.lift_eq_qe_def R.qelim_def qe_FM⇩1_def lbounds_def ubounds_def list_conj_def list_disj_def and_def or_def depends⇩R_def
lemma "qe_FM(TrueF) = TrueF"
by(simp add:qesimps)
lemma
  "qe_FM(ExQ (And (Atom(Less 0 [1])) (Atom(Less 0 [-1])))) = Atom(Less 0 [])"
by(simp add:qesimps)
lemma
 "qe_FM(ExQ (And (Atom(Less 0 [1])) (Atom(Less (- 1) [-1])))) = Atom(Less (- 1) [])"
by(simp add:qesimps)
end