(* Title: FiniteLib.thy Author: Jeremy Avigad *) header {* Facts about finite sets, sums, and products *} theory FiniteLib = Main: syntax "_qsetsum" :: "idt => bool => 'a => 'a" ("(3∑ _ | _./ _)" [0,0,10] 10) (* syntax (xsymbols) "_qsetsum" :: "idt => bool => 'a => 'a" ("(3∑_ | (_)./ _)" [0,0,10] 10) *) syntax (HTML output) "_qsetsum" :: "idt => bool => 'a => 'a" ("(3∑_ | (_)./ _)" [0,0,10] 10) translations "∑x|P. t" => "setsum (%x. t) {x. P}" print_translation {* let fun setsum_tr' [Abs(x,Tx,t), Const ("Collect",_) $ Abs(y,Ty,P)] = (if x<>y then raise Match else let val x' = Syntax.mark_bound x val t' = subst_bound(x',t) val P' = subst_bound(x',P) in Syntax.const "_qsetsum" $ Syntax.mark_bound x $ P' $ t' end) in [("setsum", setsum_tr')] end *} syntax "_from_to_setsum" :: "idt => 'a => 'a => 'b => 'b" ("(∑ _ = _.._./ _)" [0,0,0,10] 10) (* syntax (xsymbols) "_from_to_setsum" :: "idt => 'a => 'a => 'b => 'b" ("(3∑_ = _.._./ _)" [0,0,0,10] 10) *) syntax (HTML output) "_from_to_setsum" :: "idt => 'a => 'a => 'b => 'b" ("(3∑_ = _.._./ _)" [0,0,0,10] 10) translations "∑x=a..b. t" == "setsum (%x. t) {a..b}" lemma finite_union_finite_subsets: "finite S ==> ALL x:S. (finite x) ==> finite (Union S)"; by (unfold Union_def, auto); lemma setsum_cong2: "[|!!x. x ∈ A ==> f x = g x|] ==> setsum f A = setsum g A"; by (rule setsum_cong, auto); lemma setsum_const_times: "setsum (%x. (c::'a::semiring) * f x) A = c * setsum f A"; apply (case_tac "finite A"); apply (induct set: Finites); apply (simp_all add: ring_distrib); apply (simp add: setsum_def); done; lemma setsum_reindex': "[|finite B; inj_on f B|] ==> setsum h (f ` B) = setsum (%x. h(f x)) B"; apply (frule setsum_reindex); apply assumption; apply (erule ssubst); apply (unfold o_def); apply (rule refl); done; lemma setsum_reindex_cong': "[|finite A; inj_on f A; B = f ` A; g = (%x. h (f x))|] ==> setsum h B = setsum g A"; apply (frule setsum_reindex_cong); apply assumption+; apply (unfold o_def); apply assumption+; done; lemma setsum_reindex_cong'': "[|finite A; inj_on f A; B = f ` A; ALL x:A. (g x = h (f x))|] ==> setsum h B = setsum g A"; apply (subgoal_tac "setsum g A = setsum (h o f) A"); apply (subgoal_tac "setsum h B = setsum (h o f) A"); apply simp; apply (rule setsum_reindex_cong); apply assumption+; apply (rule refl); apply (rule setsum_cong); apply (simp_all add: o_def); done; lemma setsum_of_nat': "of_nat (setsum f A) = setsum (%x. of_nat(f x)) A"; apply (subst setsum_of_nat); apply (simp add: o_def); done; lemma setsum_of_int': "of_int (setsum f A) = setsum (%x. of_int(f x)) A"; apply (subst setsum_of_int); apply (simp add: o_def); done; lemma interval_singleton [simp]: "{a::'a::order..a} = {a}"; by (auto simp add: atLeastAtMost_def atMost_def atLeast_def); lemma interval_empty [simp]: "b < a ==> {a::'a::order..b} = {}"; by (auto simp add: atLeastAtMost_def atMost_def atLeast_def); lemma interval_plus_one_nat: "(n::nat) <= m ==> {n..m+1} = {n..m} Un {m+1}"; by auto; lemma setsum_range_plus_one_nat: "(n::nat) <= m ==> (∑i=n..m+1. f i) = (∑i=n..m. f i) + f(m + 1)"; apply (subst interval_plus_one_nat); apply assumption; apply (subst setsum_Un_disjoint); apply auto; done; lemma abs_setsum: "abs(setsum (f::'a=>'b::ordered_ring) A) <= setsum (%x. abs (f x)) A"; apply (case_tac "finite A"); apply (induct set: Finites); apply simp; apply simp; apply (rule order_trans); apply (rule abs_triangle_ineq); apply simp; apply (simp add: setsum_def); done; lemma setsum_nonneg': "ALL x:A. (0::'a::ordered_ring) <= f x ==> 0 <= setsum f A"; apply (case_tac "finite A"); apply (erule setsum_nonneg); apply assumption; apply (simp add: setsum_def); done; lemma setsum_nonpos: "finite A ==> ALL x : A. f x <= (0::'a::ordered_semiring) ==> setsum f A <= 0"; apply (induct set: Finites, auto); apply (subgoal_tac "f x + setsum f F <= 0 + 0", simp) apply (blast intro: add_mono); done; lemma setsum_nonpos': "ALL x : A. f x <= (0::'a::ordered_semiring) ==> setsum f A <= 0"; apply (case_tac "finite A"); apply (erule setsum_nonpos); apply assumption; apply (simp add: setsum_def); done; lemma setsum_le_cong [rule_format]: "(ALL x:A. f x <= ((g x)::'a::ordered_ring)) --> setsum f A <= setsum g A"; apply (case_tac "finite A"); apply (induct set: Finites); apply simp; apply auto; apply (erule add_mono); apply assumption; apply (simp add: setsum_def); done; lemma setsum_lt_cong: "finite A ==> A ~= {} ==> ALL x:A. (f x < ((g x)::'a::ordered_semiring)) ==> setsum f A < setsum g A"; apply (induct set: Finites); apply (force); apply (simp add: setsum_insert); apply (case_tac "F = {}"); apply force; apply (auto simp add: add_strict_mono); done; lemma setsum_negf': "(∑x:A. - (f::'a=>'b::ring) x) = - setsum f A"; apply (case_tac "finite A"); apply (erule setsum_negf); apply (simp add: setsum_def); done; lemma nat_interval_Suc: "{1..Suc n} = {1..n} Un {Suc n}"; by auto; lemma nat_setsum_Suc: "(∑i=1..Suc n. f i) = (∑i=1..n. f i) + f (Suc n)"; apply (subst nat_interval_Suc); apply (subst setsum_Un_disjoint); apply auto; done; lemma interval_plus_one_nat': "(n::nat) <= m + 1 ==> {n..m+1} = {n..m} Un {m+1}"; by auto; lemma setsum_range_plus_one_nat': "(n::nat) <= m + 1 ==> (∑i=n..m+1. f i) = (∑i=n..m. f i) + f(m + 1)"; apply (subst interval_plus_one_nat'); apply assumption; apply (subst setsum_Un_disjoint); apply auto; done; end
lemma finite_union_finite_subsets:
[| finite S; ∀x∈S. finite x |] ==> finite (Union S)
lemma setsum_cong2:
(!!x. x ∈ A ==> f x = g x) ==> setsum f A = setsum g A
lemma setsum_const_times:
(∑x∈A. c * f x) = c * setsum f A
lemma setsum_reindex':
[| finite B; inj_on f B |] ==> setsum h (f ` B) = (∑x∈B. h (f x))
lemma setsum_reindex_cong':
[| finite A; inj_on f A; B = f ` A; g = (%x. h (f x)) |] ==> setsum h B = setsum g A
lemma setsum_reindex_cong'':
[| finite A; inj_on f A; B = f ` A; ∀x∈A. g x = h (f x) |] ==> setsum h B = setsum g A
lemma setsum_of_nat':
of_nat (setsum f A) = (∑x∈A. of_nat (f x))
lemma setsum_of_int':
of_int (setsum f A) = (∑x∈A. of_int (f x))
lemma interval_singleton:
{a..a} = {a}
lemma interval_empty:
b < a ==> {a..b} = {}
lemma interval_plus_one_nat:
n ≤ m ==> {n..m + 1} = {n..m} ∪ {m + 1}
lemma setsum_range_plus_one_nat:
n ≤ m ==> setsum f {n..m + 1} = setsum f {n..m} + f (m + 1)
lemma abs_setsum:
¦setsum f A¦ ≤ (∑x∈A. ¦f x¦)
lemma setsum_nonneg':
∀x∈A. (0::'a) ≤ f x ==> (0::'a) ≤ setsum f A
lemma setsum_nonpos:
[| finite A; ∀x∈A. f x ≤ (0::'a) |] ==> setsum f A ≤ (0::'a)
lemma setsum_nonpos':
∀x∈A. f x ≤ (0::'a) ==> setsum f A ≤ (0::'a)
lemma setsum_le_cong:
(!!x. x ∈ A ==> f x ≤ g x) ==> setsum f A ≤ setsum g A
lemma setsum_lt_cong:
[| finite A; A ≠ {}; ∀x∈A. f x < g x |] ==> setsum f A < setsum g A
lemma setsum_negf':
(∑x∈A. - f x) = - setsum f A
lemma nat_interval_Suc:
{1..Suc n} = {1..n} ∪ {Suc n}
lemma nat_setsum_Suc:
setsum f {1..Suc n} = setsum f {1..n} + f (Suc n)
lemma interval_plus_one_nat':
n ≤ m + 1 ==> {n..m + 1} = {n..m} ∪ {m + 1}
lemma setsum_range_plus_one_nat':
n ≤ m + 1 ==> setsum f {n..m + 1} = setsum f {n..m} + f (m + 1)