Up to index of Isabelle/HOL/LinearQuantifierElim
theory LinArith(* ID: $Id: LinArith.thy,v 1.7 2009-01-30 14:15:31 nipkow Exp $ Author: Tobias Nipkow, 2007 *) header{* Linear real arithmetic *} theory LinArith imports QE ListVector Complex_Main begin declare iprod_assoc[simp] subsection{*Basics*} subsubsection{*Syntax and Semantics*} datatype atom = Less real "real list" | Eq real "real list" fun is_Less :: "atom => bool" where "is_Less (Less r rs) = True" | "is_Less f = False" abbreviation "is_Eq ≡ Not o is_Less" lemma is_Less_iff: "is_Less f = (∃r rs. f = Less r rs)" by(induct f) auto lemma is_Eq_iff: "(∀i j. a ≠ Less i j) = (∃i j. a = Eq i j)" by(cases a) auto fun negR :: "atom => atom fm" where "negR (Less r t) = Or (Atom(Less (-r) (-t))) (Atom(Eq r t))" | "negR (Eq r t) = Or (Atom(Less r t)) (Atom(Less (-r) (-t)))" fun hd_coeff :: "atom => real" where "hd_coeff (Less r cs) = (case cs of [] => 0 | c#_ => c)" | "hd_coeff (Eq r cs) = (case cs of [] => 0 | c#_ => c)" definition "dependsR a = (hd_coeff a ≠ 0)" fun decrR :: "atom => atom" where "decrR (Less r rs) = Less r (tl rs)" | "decrR (Eq r rs) = Eq r (tl rs)" fun IR :: "atom => real list => bool" where "IR (Less r cs) xs = (r < 〈cs,xs〉)" | "IR (Eq r cs) xs = (r = 〈cs,xs〉)" definition "atoms0 = ATOM.atoms0 dependsR" (* FIXME !!! (incl: display should hide params)*) interpretation R!: ATOM negR "(λa. True)" IR dependsR decrR where "ATOM.atoms0 dependsR = atoms0" proof - case goal1 thus ?case apply(unfold_locales) apply(case_tac a) apply simp_all apply(case_tac a) apply simp_all apply arith apply arith apply(case_tac a) apply(simp_all add:dependsR_def split:list.splits) done next case goal2 thus ?case by(simp add:atoms0_def) qed setup {* Sign.revert_abbrev "" @{const_name R.I} *} setup {* Sign.revert_abbrev "" @{const_name R.lift_nnf_qe} *} subsubsection{*Shared constructions*} fun combine :: "(real * real list) => (real * real list) => atom" where "combine (r1,cs1) (r2,cs2) = Less (r1-r2) (cs2 - cs1)" (* More efficient combination than rhs of combine_conv below; unused lemma combine_code: "combine (r1,c1,cs1) (r2,c2,cs2) = Less (c1*r2-c2*r1) (zipwith0 (%x y. c1*y-c2*x) cs1 cs2)" apply(rule sym) apply(simp) apply(induct cs1 arbitrary:cs2) apply simp apply(case_tac cs2) apply simp apply simp done*) definition "lbounds as = [(r/c, (-1/c) *s cs). Less r (c#cs) \<leftarrow> as, c>0]" definition "ubounds as = [(r/c, (-1/c) *s cs). Less r (c#cs) \<leftarrow> as, c<0]" definition "ebounds as = [(r/c, (-1/c) *s cs). Eq r (c#cs) \<leftarrow> as, c≠0]" lemma set_lbounds: "set(lbounds as) = {(r/c, (-1/c) *s cs)|r c cs. Less r (c#cs) : set as ∧ c>0}" by(force simp: lbounds_def split:list.splits atom.splits if_splits) lemma set_ubounds: "set(ubounds as) = {(r/c, (-1/c) *s cs)|r c cs. Less r (c#cs) : set as ∧ c<0}" by(force simp: ubounds_def split:list.splits atom.splits if_splits) lemma set_ebounds: "set(ebounds as) = {(r/c, (-1/c) *s cs)|r c cs. Eq r (c#cs) : set as ∧ c≠0}" by(force simp: ebounds_def split:list.splits atom.splits if_splits) abbreviation EQ where "EQ f xs ≡ {(r - 〈cs,xs〉)/c|r c cs. Eq r (c#cs) : set(R.atoms0 f) ∧ c≠0}" abbreviation LB where "LB f xs ≡ {(r - 〈cs,xs〉)/c|r c cs. Less r (c#cs) : set(R.atoms0 f) ∧ c>0}" abbreviation UB where "UB f xs ≡ {(r - 〈cs,xs〉)/c|r c cs. Less r (c#cs) : set(R.atoms0 f) ∧ c<0}" fun asubst :: "real * real list => atom => atom" where "asubst (r,cs) (Less s (d#ds)) = Less (s - d*r) (d *s cs + ds)" | "asubst (r,cs) (Eq s (d#ds)) = Eq (s - d*r) (d *s cs + ds)" | "asubst (r,cs) (Less s []) = Less s []" | "asubst (r,cs) (Eq s []) = Eq s []" abbreviation "subst φ rcs ≡ mapfm (asubst rcs) φ" definition eval :: "real * real list => real list => real" where "eval rcs xs = fst rcs + 〈snd rcs,xs〉" lemma I_asubst: "IR (asubst t a) xs = IR a (eval t xs # xs)" proof(cases a) case (Less r cs) thus ?thesis by(cases t, cases cs, simp_all add:eval_def right_distrib iprod_left_add_distrib) arith next case (Eq r cs) thus ?thesis by(cases t, cases cs, simp_all add:eval_def right_distrib iprod_left_add_distrib) arith qed lemma I_subst: "qfree φ ==> R.I (subst φ t) xs = R.I φ (eval t xs # xs)" by(induct φ)(simp_all add:I_asubst) lemma I_subst_pretty: "qfree φ ==> R.I (subst φ (r,cs)) xs = R.I φ ((r + 〈cs,xs〉) # xs)" by(simp add:I_subst eval_def) fun min_inf :: "atom fm => atom fm" ("inf-") where "inf- (And φ1 φ2) = and (inf- φ1) (inf- φ2)" | "inf- (Or φ1 φ2) = or (inf- φ1) (inf- φ2)" | "inf- (Atom(Less r (c#cs))) = (if c<0 then TrueF else if c>0 then FalseF else Atom(Less r cs))" | "inf- (Atom(Eq r (c#cs))) = (if c=0 then Atom(Eq r cs) else FalseF)" | "inf- φ = φ" fun plus_inf :: "atom fm => atom fm" ("inf+") where "inf+ (And φ1 φ2) = and (inf+ φ1) (inf+ φ2)" | "inf+ (Or φ1 φ2) = or (inf+ φ1) (inf+ φ2)" | "inf+ (Atom(Less r (c#cs))) = (if c>0 then TrueF else if c<0 then FalseF else Atom(Less r cs))" | "inf+ (Atom(Eq r (c#cs))) = (if c=0 then Atom(Eq r cs) else FalseF)" | "inf+ φ = φ" lemma qfree_min_inf: "qfree φ ==> qfree(inf- φ)" by(induct φ rule:min_inf.induct) simp_all lemma qfree_plus_inf: "qfree φ ==> qfree(inf+ φ)" by(induct φ rule:plus_inf.induct) simp_all lemma min_inf: "nqfree f ==> ∃x. ∀y≤x. R.I (inf- f) xs = R.I f (y # xs)" (is "_ ==> ∃x. ?P f x") proof(induct f) case (Atom a) show ?case proof (cases a) case (Less r cs) show ?thesis proof(cases cs) case Nil thus ?thesis using Less by simp next case (Cons c cs) { assume "c=0" hence ?thesis using Less Cons by simp } moreover { assume "c<0" hence "?P (Atom a) ((r - 〈cs,xs〉 + 1)/c)" using Less Cons by(auto simp add: field_simps) hence ?thesis .. } moreover { assume "c>0" hence "?P (Atom a) ((r - 〈cs,xs〉 - 1)/c)" using Less Cons by(auto simp add: field_simps) hence ?thesis .. } ultimately show ?thesis by force qed next case (Eq r cs) show ?thesis proof(cases cs) case Nil thus ?thesis using Eq by simp next case (Cons c cs) { assume "c=0" hence ?thesis using Eq Cons by simp } moreover { assume "c<0" hence "?P (Atom a) ((r - 〈cs,xs〉 + 1)/c)" using Eq Cons by(auto simp add: field_simps) hence ?thesis .. } moreover { assume "c>0" hence "?P (Atom a) ((r - 〈cs,xs〉 - 1)/c)" using Eq Cons by(auto simp add: field_simps) hence ?thesis .. } ultimately show ?thesis by force qed qed next case (And f1 f2) then obtain x1 x2 where "?P f1 x1" "?P f2 x2" by fastsimp+ hence "?P (And f1 f2) (min x1 x2)" by(force simp:and_def) thus ?case .. next case (Or f1 f2) then obtain x1 x2 where "?P f1 x1" "?P f2 x2" by fastsimp+ hence "?P (Or f1 f2) (min x1 x2)" by(force simp:or_def) thus ?case .. qed simp_all lemma plus_inf: "nqfree f ==> ∃x. ∀y≥x. R.I (inf+ f) xs = R.I f (y # xs)" (is "_ ==> ∃x. ?P f x") proof(induct f) case (Atom a) show ?case proof (cases a) case (Less r cs) show ?thesis proof(cases cs) case Nil thus ?thesis using Less by simp next case (Cons c cs) { assume "c=0" hence ?thesis using Less Cons by simp } moreover { assume "c<0" hence "?P (Atom a) ((r - 〈cs,xs〉 - 1)/c)" using Less Cons by(auto simp add: field_simps) hence ?thesis .. } moreover { assume "c>0" hence "?P (Atom a) ((r - 〈cs,xs〉 + 1)/c)" using Less Cons by(auto simp add: field_simps) hence ?thesis .. } ultimately show ?thesis by force qed next case (Eq r cs) show ?thesis proof(cases cs) case Nil thus ?thesis using Eq by simp next case (Cons c cs) { assume "c=0" hence ?thesis using Eq Cons by simp } moreover { assume "c<0" hence "?P (Atom a) ((r - 〈cs,xs〉 - 1)/c)" using Eq Cons by(auto simp add: field_simps) hence ?thesis .. } moreover { assume "c>0" hence "?P (Atom a) ((r - 〈cs,xs〉 + 1)/c)" using Eq Cons by(auto simp add: field_simps) hence ?thesis .. } ultimately show ?thesis by force qed qed next case (And f1 f2) then obtain x1 x2 where "?P f1 x1" "?P f2 x2" by fastsimp+ hence "?P (And f1 f2) (max x1 x2)" by(force simp:and_def) thus ?case .. next case (Or f1 f2) then obtain x1 x2 where "?P f1 x1" "?P f2 x2" by fastsimp+ hence "?P (Or f1 f2) (max x1 x2)" by(force simp:or_def) thus ?case .. qed simp_all declare [[simp_depth_limit = 2]] lemma LBex: "[| nqfree f; R.I f (x#xs); ¬R.I (inf- f) xs; x ∉ EQ f xs |] ==> ∃l∈ LB f xs. l < x" apply(induct f) apply simp apply simp apply(case_tac a) apply(simp add: dependsR_def split:if_splits list.splits) apply(simp add: field_simps) apply (fastsimp simp add: dependsR_def split:if_splits list.splits) apply fastsimp apply fastsimp apply simp apply simp done lemma UBex: "[| nqfree f; R.I f (x#xs); ¬R.I (inf+ f) xs; x ∉ EQ f xs |] ==> ∃u∈ UB f xs. x < u" apply(induct f) apply simp apply simp apply(case_tac a) apply(simp add: dependsR_def split:if_splits list.splits) apply(simp add: field_simps) apply (fastsimp simp add: dependsR_def split:if_splits list.splits) apply fastsimp apply fastsimp apply simp apply simp done declare [[simp_depth_limit = 50]] lemma finite_LB: "finite(LB f xs)" proof - have "LB f xs = (λ(r,cs). r + 〈cs,xs〉) ` set(lbounds(R.atoms0 f))" by (force simp:set_lbounds image_def field_simps) thus ?thesis by simp qed lemma finite_UB: "finite(UB f xs)" proof - have "UB f xs = (λ(r,cs). r + 〈cs,xs〉) ` set(ubounds(R.atoms0 f))" by (force simp:set_ubounds image_def field_simps) thus ?thesis by simp qed end