# HG changeset patch # User ballarin # Date 1051689695 -7200 # Node ID d3671b87882871607794b7b97101efa7e2c3c4ec # Parent 4822d9597d1e4a5d40eb7f49fa7428480c83de5b Greatly extended CRing. Added Module. diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/CRing.thy --- a/src/HOL/Algebra/CRing.thy Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/CRing.thy Wed Apr 30 10:01:35 2003 +0200 @@ -5,41 +5,294 @@ Copyright: Clemens Ballarin *) -theory CRing = Summation +theory CRing = FiniteProduct files ("ringsimp.ML"): +section {* Abelian Groups *} + +record 'a ring = "'a monoid" + + zero :: 'a ("\\") + add :: "['a, 'a] => 'a" (infixl "\\" 65) + +text {* Derived operations. *} + +constdefs + a_inv :: "[('a, 'm) ring_scheme, 'a ] => 'a" ("\\ _" [81] 80) + "a_inv R == m_inv (| carrier = carrier R, mult = add R, one = zero R |)" + + minus :: "[('a, 'm) ring_scheme, 'a, 'a] => 'a" (infixl "\\" 65) + "[| x \ carrier R; y \ carrier R |] ==> minus R x y == add R x (a_inv R y)" + +locale abelian_monoid = struct G + + assumes a_comm_monoid: "comm_monoid (| carrier = carrier G, + mult = add G, one = zero G |)" + +text {* + The following definition is redundant but simple to use. +*} + +locale abelian_group = abelian_monoid + + assumes a_comm_group: "comm_group (| carrier = carrier G, + mult = add G, one = zero G |)" + +subsection {* Basic Properties *} + +lemma abelian_monoidI: + assumes a_closed: + "!!x y. [| x \ carrier R; y \ carrier R |] ==> add R x y \ carrier R" + and zero_closed: "zero R \ carrier R" + and a_assoc: + "!!x y z. [| x \ carrier R; y \ carrier R; z \ carrier R |] ==> + add R (add R x y) z = add R x (add R y z)" + and l_zero: "!!x. x \ carrier R ==> add R (zero R) x = x" + and a_comm: + "!!x y. [| x \ carrier R; y \ carrier R |] ==> add R x y = add R y x" + shows "abelian_monoid R" + by (auto intro!: abelian_monoid.intro comm_monoidI intro: prems) + +lemma abelian_groupI: + assumes a_closed: + "!!x y. [| x \ carrier R; y \ carrier R |] ==> add R x y \ carrier R" + and zero_closed: "zero R \ carrier R" + and a_assoc: + "!!x y z. [| x \ carrier R; y \ carrier R; z \ carrier R |] ==> + add R (add R x y) z = add R x (add R y z)" + and a_comm: + "!!x y. [| x \ carrier R; y \ carrier R |] ==> add R x y = add R y x" + and l_zero: "!!x. x \ carrier R ==> add R (zero R) x = x" + and l_inv_ex: "!!x. x \ carrier R ==> EX y : carrier R. add R y x = zero R" + shows "abelian_group R" + by (auto intro!: abelian_group.intro abelian_monoidI + abelian_group_axioms.intro comm_monoidI comm_groupI + intro: prems) + +(* TODO: The following thms are probably unnecessary. *) + +lemma (in abelian_monoid) a_magma: + "magma (| carrier = carrier G, mult = add G, one = zero G |)" + by (rule comm_monoid.axioms) (rule a_comm_monoid) + +lemma (in abelian_monoid) a_semigroup: + "semigroup (| carrier = carrier G, mult = add G, one = zero G |)" + by (unfold semigroup_def) (fast intro: comm_monoid.axioms a_comm_monoid) + +lemma (in abelian_monoid) a_monoid: + "monoid (| carrier = carrier G, mult = add G, one = zero G |)" + by (unfold monoid_def) (fast intro: a_comm_monoid comm_monoid.axioms) + +lemma (in abelian_group) a_group: + "group (| carrier = carrier G, mult = add G, one = zero G |)" + by (unfold group_def semigroup_def) + (fast intro: comm_group.axioms a_comm_group) + +lemma (in abelian_monoid) a_comm_semigroup: + "comm_semigroup (| carrier = carrier G, mult = add G, one = zero G |)" + by (unfold comm_semigroup_def semigroup_def) + (fast intro: comm_monoid.axioms a_comm_monoid) + +lemmas monoid_record_simps = semigroup.simps monoid.simps + +lemma (in abelian_monoid) a_closed [intro, simp]: + "[| x \ carrier G; y \ carrier G |] ==> x \ y \ carrier G" + by (rule magma.m_closed [OF a_magma, simplified monoid_record_simps]) + +lemma (in abelian_monoid) zero_closed [intro, simp]: + "\ \ carrier G" + by (rule monoid.one_closed [OF a_monoid, simplified monoid_record_simps]) + +lemma (in abelian_group) a_inv_closed [intro, simp]: + "x \ carrier G ==> \ x \ carrier G" + by (simp add: a_inv_def + group.inv_closed [OF a_group, simplified monoid_record_simps]) + +lemma (in abelian_group) minus_closed [intro, simp]: + "[| x \ carrier G; y \ carrier G |] ==> x \ y \ carrier G" + by (simp add: minus_def) + +lemma (in abelian_group) a_l_cancel [simp]: + "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + (x \ y = x \ z) = (y = z)" + by (rule group.l_cancel [OF a_group, simplified monoid_record_simps]) + +lemma (in abelian_group) a_r_cancel [simp]: + "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + (y \ x = z \ x) = (y = z)" + by (rule group.r_cancel [OF a_group, simplified monoid_record_simps]) + +lemma (in abelian_monoid) a_assoc: + "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + (x \ y) \ z = x \ (y \ z)" + by (rule semigroup.m_assoc [OF a_semigroup, simplified monoid_record_simps]) + +lemma (in abelian_monoid) l_zero [simp]: + "x \ carrier G ==> \ \ x = x" + by (rule monoid.l_one [OF a_monoid, simplified monoid_record_simps]) + +lemma (in abelian_group) l_neg: + "x \ carrier G ==> \ x \ x = \" + by (simp add: a_inv_def + group.l_inv [OF a_group, simplified monoid_record_simps]) + +lemma (in abelian_monoid) a_comm: + "[| x \ carrier G; y \ carrier G |] ==> x \ y = y \ x" + by (rule comm_semigroup.m_comm [OF a_comm_semigroup, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) a_lcomm: + "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + x \ (y \ z) = y \ (x \ z)" + by (rule comm_semigroup.m_lcomm [OF a_comm_semigroup, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) r_zero [simp]: + "x \ carrier G ==> x \ \ = x" + using monoid.r_one [OF a_monoid] + by simp + +lemma (in abelian_group) r_neg: + "x \ carrier G ==> x \ (\ x) = \" + using group.r_inv [OF a_group] + by (simp add: a_inv_def) + +lemma (in abelian_group) minus_zero [simp]: + "\ \ = \" + by (simp add: a_inv_def + group.inv_one [OF a_group, simplified monoid_record_simps]) + +lemma (in abelian_group) minus_minus [simp]: + "x \ carrier G ==> \ (\ x) = x" + using group.inv_inv [OF a_group, simplified monoid_record_simps] + by (simp add: a_inv_def) + +lemma (in abelian_group) a_inv_inj: + "inj_on (a_inv G) (carrier G)" + using group.inv_inj [OF a_group, simplified monoid_record_simps] + by (simp add: a_inv_def) + +lemma (in abelian_group) minus_add: + "[| x \ carrier G; y \ carrier G |] ==> \ (x \ y) = \ x \ \ y" + using comm_group.inv_mult [OF a_comm_group] + by (simp add: a_inv_def) + +lemmas (in abelian_monoid) a_ac = a_assoc a_comm a_lcomm + +subsection {* Sums over Finite Sets *} + +text {* + This definition makes it easy to lift lemmas from @{term finprod}. +*} + +constdefs + finsum :: "[('b, 'm) ring_scheme, 'a => 'b, 'a set] => 'b" + "finsum G f A == finprod (| carrier = carrier G, + mult = add G, one = zero G |) f A" + +(* + lemmas (in abelian_monoid) finsum_empty [simp] = + comm_monoid.finprod_empty [OF a_comm_monoid, simplified] + is dangeous, because attributes (like simplified) are applied upon opening + the locale, simplified refers to the simpset at that time!!! + + lemmas (in abelian_monoid) finsum_empty [simp] = + abelian_monoid.finprod_empty [OF a_abelian_monoid, folded finsum_def, + simplified monoid_record_simps] +makes the locale slow, because proofs are repeated for every +"lemma (in abelian_monoid)" command. +When lemma is used time in UnivPoly.thy from beginning to UP_cring goes down +from 110 secs to 60 secs. +*) + +lemma (in abelian_monoid) finsum_empty [simp]: + "finsum G f {} = \" + by (rule comm_monoid.finprod_empty [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_insert [simp]: + "[| finite F; a \ F; f \ F -> carrier G; f a \ carrier G |] + ==> finsum G f (insert a F) = f a \ finsum G f F" + by (rule comm_monoid.finprod_insert [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_zero [simp]: + "finite A ==> finsum G (%i. \) A = \" + by (rule comm_monoid.finprod_one [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_closed [simp]: + fixes A + assumes fin: "finite A" and f: "f \ A -> carrier G" + shows "finsum G f A \ carrier G" + by (rule comm_monoid.finprod_closed [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_Un_Int: + "[| finite A; finite B; g \ A -> carrier G; g \ B -> carrier G |] ==> + finsum G g (A Un B) \ finsum G g (A Int B) = + finsum G g A \ finsum G g B" + by (rule comm_monoid.finprod_Un_Int [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_Un_disjoint: + "[| finite A; finite B; A Int B = {}; + g \ A -> carrier G; g \ B -> carrier G |] + ==> finsum G g (A Un B) = finsum G g A \ finsum G g B" + by (rule comm_monoid.finprod_Un_disjoint [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_addf: + "[| finite A; f \ A -> carrier G; g \ A -> carrier G |] ==> + finsum G (%x. f x \ g x) A = (finsum G f A \ finsum G g A)" + by (rule comm_monoid.finprod_multf [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_cong': + "[| A = B; g : B -> carrier G; + !!i. i : B ==> f i = g i |] ==> finsum G f A = finsum G g B" + by (rule comm_monoid.finprod_cong' [OF a_comm_monoid, + folded finsum_def, simplified monoid_record_simps]) auto + +lemma (in abelian_monoid) finsum_0 [simp]: + "f : {0::nat} -> carrier G ==> finsum G f {..0} = f 0" + by (rule comm_monoid.finprod_0 [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_Suc [simp]: + "f : {..Suc n} -> carrier G ==> + finsum G f {..Suc n} = (f (Suc n) \ finsum G f {..n})" + by (rule comm_monoid.finprod_Suc [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_Suc2: + "f : {..Suc n} -> carrier G ==> + finsum G f {..Suc n} = (finsum G (%i. f (Suc i)) {..n} \ f 0)" + by (rule comm_monoid.finprod_Suc2 [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_add [simp]: + "[| f : {..n} -> carrier G; g : {..n} -> carrier G |] ==> + finsum G (%i. f i \ g i) {..n::nat} = + finsum G f {..n} \ finsum G g {..n}" + by (rule comm_monoid.finprod_mult [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) + +lemma (in abelian_monoid) finsum_cong: + "[| A = B; !!i. i : B ==> f i = g i; + g : B -> carrier G = True |] ==> finsum G f A = finsum G g B" + by (rule comm_monoid.finprod_cong [OF a_comm_monoid, folded finsum_def, + simplified monoid_record_simps]) auto + +text {*Usually, if this rule causes a failed congruence proof error, + the reason is that the premise @{text "g \ B -> carrier G"} cannot be shown. + Adding @{thm [source] Pi_def} to the simpset is often useful. *} + section {* The Algebraic Hierarchy of Rings *} subsection {* Basic Definitions *} -record 'a ring = "'a group" + - zero :: 'a ("\\") - add :: "['a, 'a] => 'a" (infixl "\\" 65) - a_inv :: "'a => 'a" ("\\ _" [81] 80) - -locale cring = abelian_monoid R + - assumes a_abelian_group: "abelian_group (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - and m_inv_def: "[| EX y. y \ carrier R & x \ y = \; x \ carrier R |] - ==> inv x = (THE y. y \ carrier R & x \ y = \)" - and l_distr: "[| x \ carrier R; y \ carrier R; z \ carrier R |] +locale cring = abelian_group R + comm_monoid R + + assumes l_distr: "[| x \ carrier R; y \ carrier R; z \ carrier R |] ==> (x \ y) \ z = x \ z \ y \ z" -text {* Derived operation. *} - -constdefs - minus :: "[('a, 'm) ring_scheme, 'a, 'a] => 'a" (infixl "\\" 65) - "[| x \ carrier R; y \ carrier R |] ==> minus R x y == add R x (a_inv R y)" - -(* - -- {* Definition of derived operations *} - - minus_def: "a - b = a + (-b)" - inverse_def: "inverse a = (if a dvd 1 then THE x. a*x = 1 else 0)" - divide_def: "a / b = a * inverse b" - power_def: "a ^ n = nat_rec 1 (%u b. b * a) n" -*) - locale "domain" = cring + assumes one_not_zero [simp]: "\ ~= \" and integral: "[| a \ b = \; a \ carrier R; b \ carrier R |] ==> @@ -47,117 +300,41 @@ subsection {* Basic Facts of Rings *} -lemma (in cring) a_magma [simp, intro]: - "magma (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - using a_abelian_group by (simp only: abelian_group_def) - -lemma (in cring) a_l_one [simp, intro]: - "l_one (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - using a_abelian_group by (simp only: abelian_group_def) - -lemma (in cring) a_abelian_group_parts [simp, intro]: - "semigroup_axioms (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - "group_axioms (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - "abelian_semigroup_axioms (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - using a_abelian_group by (simp_all only: abelian_group_def) - -lemma (in cring) a_semigroup: - "semigroup (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - by (simp add: semigroup_def) - -lemma (in cring) a_group: - "group (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - by (simp add: group_def) - -lemma (in cring) a_abelian_semigroup: - "abelian_semigroup (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - by (simp add: abelian_semigroup_def) - -lemmas group_record_simps = semigroup.simps monoid.simps group.simps - -lemmas (in cring) a_closed [intro, simp] = - magma.m_closed [OF a_magma, simplified group_record_simps] - -lemmas (in cring) zero_closed [intro, simp] = - l_one.one_closed [OF a_l_one, simplified group_record_simps] - -lemmas (in cring) a_inv_closed [intro, simp] = - group.inv_closed [OF a_group, simplified group_record_simps] +lemma cringI: + assumes abelian_group: "abelian_group R" + and comm_monoid: "comm_monoid R" + and l_distr: "!!x y z. [| x \ carrier R; y \ carrier R; z \ carrier R |] + ==> mult R (add R x y) z = add R (mult R x z) (mult R y z)" + shows "cring R" + by (auto intro: cring.intro + abelian_group.axioms comm_monoid.axioms cring_axioms.intro prems) -lemma (in cring) minus_closed [intro, simp]: - "[| x \ carrier R; y \ carrier R |] ==> x \ y \ carrier R" - by (simp add: minus_def) - -lemmas (in cring) a_l_cancel [simp] = - group.l_cancel [OF a_group, simplified group_record_simps] - -lemmas (in cring) a_r_cancel [simp] = - group.r_cancel [OF a_group, simplified group_record_simps] - -lemmas (in cring) a_assoc = - semigroup.m_assoc [OF a_semigroup, simplified group_record_simps] - -lemmas (in cring) l_zero [simp] = - l_one.l_one [OF a_l_one, simplified group_record_simps] - -lemmas (in cring) l_neg = - group.l_inv [OF a_group, simplified group_record_simps] - -lemmas (in cring) a_comm = - abelian_semigroup.m_comm [OF a_abelian_semigroup, - simplified group_record_simps] +lemma (in cring) is_abelian_group: + "abelian_group R" + by (auto intro!: abelian_groupI a_assoc a_comm l_neg) -lemmas (in cring) a_lcomm = - abelian_semigroup.m_lcomm [OF a_abelian_semigroup, simplified group_record_simps] - -lemma (in cring) r_zero [simp]: - "x \ carrier R ==> x \ \ = x" - using group.r_one [OF a_group] - by simp - -lemma (in cring) r_neg: - "x \ carrier R ==> x \ (\ x) = \" - using group.r_inv [OF a_group] - by simp - -lemmas (in cring) minus_zero [simp] = - group.inv_one [OF a_group, simplified group_record_simps] - -lemma (in cring) minus_minus [simp]: - "x \ carrier R ==> \ (\ x) = x" - using group.inv_inv [OF a_group, simplified group_record_simps] - by simp - -lemma (in cring) minus_add: - "[| x \ carrier R; y \ carrier R |] ==> \ (x \ y) = \ x \ \ y" - using abelian_group.inv_mult [OF a_abelian_group] - by simp - -lemmas (in cring) a_ac = a_assoc a_comm a_lcomm +lemma (in cring) is_comm_monoid: + "comm_monoid R" + by (auto intro!: comm_monoidI m_assoc m_comm) subsection {* Normaliser for Commutative Rings *} -lemma (in cring) r_neg2: - "[| x \ carrier R; y \ carrier R |] ==> x \ (\ x \ y) = y" +lemma (in abelian_group) r_neg2: + "[| x \ carrier G; y \ carrier G |] ==> x \ (\ x \ y) = y" proof - - assume G: "x \ carrier R" "y \ carrier R" - then have "(x \ \ x) \ y = y" by (simp only: r_neg l_zero) - with G show ?thesis by (simp add: a_ac) + assume G: "x \ carrier G" "y \ carrier G" + then have "(x \ \ x) \ y = y" + by (simp only: r_neg l_zero) + with G show ?thesis + by (simp add: a_ac) qed -lemma (in cring) r_neg1: - "[| x \ carrier R; y \ carrier R |] ==> \ x \ (x \ y) = y" +lemma (in abelian_group) r_neg1: + "[| x \ carrier G; y \ carrier G |] ==> \ x \ (x \ y) = y" proof - - assume G: "x \ carrier R" "y \ carrier R" - then have "(\ x \ x) \ y = y" by (simp only: l_neg l_zero) + assume G: "x \ carrier G" "y \ carrier G" + then have "(\ x \ x) \ y = y" + by (simp only: l_neg l_zero) with G show ?thesis by (simp add: a_ac) qed @@ -165,10 +342,10 @@ "[| x \ carrier R; y \ carrier R; z \ carrier R |] ==> z \ (x \ y) = z \ x \ z \ y" proof - - assume G: "x \ carrier R" "y \ carrier R" "z \ carrier R" + assume R: "x \ carrier R" "y \ carrier R" "z \ carrier R" then have "z \ (x \ y) = (x \ y) \ z" by (simp add: m_comm) - also from G have "... = x \ z \ y \ z" by (simp add: l_distr) - also from G have "... = z \ x \ z \ y" by (simp add: m_comm) + also from R have "... = x \ z \ y \ z" by (simp add: l_distr) + also from R have "... = z \ x \ z \ y" by (simp add: m_comm) finally show ?thesis . qed @@ -191,7 +368,7 @@ "x \ carrier R ==> x \ \ = \" proof - assume R: "x \ carrier R" - then have "x \ \ = \ \ x" by (simp add: ac) + then have "x \ \ = \ \ x" by (simp add: m_ac) also from R have "... = \" by simp finally show ?thesis . qed @@ -211,15 +388,19 @@ "[| x \ carrier R; y \ carrier R |] ==> x \ \ y = \ (x \ y)" proof - assume R: "x \ carrier R" "y \ carrier R" - then have "x \ \ y = \ y \ x" by (simp add: ac) + then have "x \ \ y = \ y \ x" by (simp add: m_ac) also from R have "... = \ (y \ x)" by (simp add: l_minus) - also from R have "... = \ (x \ y)" by (simp add: ac) + also from R have "... = \ (x \ y)" by (simp add: m_ac) finally show ?thesis . qed +lemma (in cring) minus_eq: + "[| x \ carrier R; y \ carrier R |] ==> x \ y = x \ \ y" + by (simp only: minus_def) + lemmas (in cring) cring_simprules = a_closed zero_closed a_inv_closed minus_closed m_closed one_closed - a_assoc l_zero l_neg a_comm m_assoc l_one l_distr m_comm minus_def + a_assoc l_zero l_neg a_comm m_assoc l_one l_distr m_comm minus_eq r_zero r_neg r_neg2 r_neg1 minus_add minus_minus minus_zero a_lcomm m_lcomm r_distr l_null r_null l_minus r_minus @@ -227,7 +408,11 @@ method_setup algebra = {* Method.ctxt_args cring_normalise *} - {* computes distributive normal form in commutative rings (locales version) *} + {* computes distributive normal form in locale context cring *} + +lemma (in cring) nat_pow_zero: + "(n::nat) ~= 0 ==> \ (^) n = \" + by (induct n) simp_all text {* Two examples for use of method algebra *} @@ -244,83 +429,6 @@ subsection {* Sums over Finite Sets *} -text {* - This definition makes it easy to lift lemmas from @{term finprod}. -*} - -constdefs - finsum :: "[('b, 'm) ring_scheme, 'a => 'b, 'a set] => 'b" - "finsum R f A == finprod (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |) f A" - -lemma (in cring) a_abelian_monoid: - "abelian_monoid (| carrier = carrier R, - mult = add R, one = zero R, m_inv = a_inv R |)" - by (simp add: abelian_monoid_def) - -(* - lemmas (in cring) finsum_empty [simp] = - abelian_monoid.finprod_empty [OF a_abelian_monoid, simplified] - is dangeous, because attributes (like simplified) are applied upon opening - the locale, simplified refers to the simpset at that time!!! -*) - -lemmas (in cring) finsum_empty [simp] = - abelian_monoid.finprod_empty [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_insert [simp] = - abelian_monoid.finprod_insert [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_zero = - abelian_monoid.finprod_one [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_closed [simp] = - abelian_monoid.finprod_closed [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_Un_Int = - abelian_monoid.finprod_Un_Int [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_Un_disjoint = - abelian_monoid.finprod_Un_disjoint [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_addf = - abelian_monoid.finprod_multf [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_cong' = - abelian_monoid.finprod_cong' [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_0 [simp] = - abelian_monoid.finprod_0 [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_Suc [simp] = - abelian_monoid.finprod_Suc [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_Suc2 = - abelian_monoid.finprod_Suc2 [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_add [simp] = - abelian_monoid.finprod_mult [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -lemmas (in cring) finsum_cong = - abelian_monoid.finprod_cong [OF a_abelian_monoid, folded finsum_def, - simplified group_record_simps] - -text {*Usually, if this rule causes a failed congruence proof error, - the reason is that the premise @{text "g \ B -> carrier G"} cannot be shown. - Adding @{thm [source] Pi_def} to the simpset is often useful. *} - lemma (in cring) finsum_ldistr: "[| finite A; a \ carrier R; f \ A -> carrier R |] ==> finsum R f A \ a = finsum R (%i. f i \ a) A" @@ -380,4 +488,90 @@ with R show ?thesis by algebra qed +subsection {* Morphisms *} + +constdefs + ring_hom :: "[('a, 'm) ring_scheme, ('b, 'n) ring_scheme] => ('a => 'b) set" + "ring_hom R S == {h. h \ carrier R -> carrier S & + (ALL x y. x \ carrier R & y \ carrier R --> + h (mult R x y) = mult S (h x) (h y) & + h (add R x y) = add S (h x) (h y)) & + h (one R) = one S}" + +lemma ring_hom_memI: + assumes hom_closed: "!!x. x \ carrier R ==> h x \ carrier S" + and hom_mult: "!!x y. [| x \ carrier R; y \ carrier R |] ==> + h (mult R x y) = mult S (h x) (h y)" + and hom_add: "!!x y. [| x \ carrier R; y \ carrier R |] ==> + h (add R x y) = add S (h x) (h y)" + and hom_one: "h (one R) = one S" + shows "h \ ring_hom R S" + by (auto simp add: ring_hom_def prems Pi_def) + +lemma ring_hom_closed: + "[| h \ ring_hom R S; x \ carrier R |] ==> h x \ carrier S" + by (auto simp add: ring_hom_def funcset_mem) + +lemma ring_hom_mult: + "[| h \ ring_hom R S; x \ carrier R; y \ carrier R |] ==> + h (mult R x y) = mult S (h x) (h y)" + by (simp add: ring_hom_def) + +lemma ring_hom_add: + "[| h \ ring_hom R S; x \ carrier R; y \ carrier R |] ==> + h (add R x y) = add S (h x) (h y)" + by (simp add: ring_hom_def) + +lemma ring_hom_one: + "h \ ring_hom R S ==> h (one R) = one S" + by (simp add: ring_hom_def) + +locale ring_hom_cring = cring R + cring S + var h + + assumes homh [simp, intro]: "h \ ring_hom R S" + notes hom_closed [simp, intro] = ring_hom_closed [OF homh] + and hom_mult [simp] = ring_hom_mult [OF homh] + and hom_add [simp] = ring_hom_add [OF homh] + and hom_one [simp] = ring_hom_one [OF homh] + +lemma (in ring_hom_cring) hom_zero [simp]: + "h \ = \\<^sub>2" +proof - + have "h \ \\<^sub>2 h \ = h \ \\<^sub>2 \\<^sub>2" + by (simp add: hom_add [symmetric] del: hom_add) + then show ?thesis by (simp del: S.r_zero) +qed + +lemma (in ring_hom_cring) hom_a_inv [simp]: + "x \ carrier R ==> h (\ x) = \\<^sub>2 h x" +proof - + assume R: "x \ carrier R" + then have "h x \\<^sub>2 h (\ x) = h x \\<^sub>2 (\\<^sub>2 h x)" + by (simp add: hom_add [symmetric] R.r_neg S.r_neg del: hom_add) + with R show ?thesis by simp +qed + +lemma (in ring_hom_cring) hom_finsum [simp]: + "[| finite A; f \ A -> carrier R |] ==> + h (finsum R f A) = finsum S (h o f) A" +proof (induct set: Finites) + case empty then show ?case by simp +next + case insert then show ?case by (simp add: Pi_def) +qed + +lemma (in ring_hom_cring) hom_finprod: + "[| finite A; f \ A -> carrier R |] ==> + h (finprod R f A) = finprod S (h o f) A" +proof (induct set: Finites) + case empty then show ?case by simp +next + case insert then show ?case by (simp add: Pi_def) +qed + +declare ring_hom_cring.hom_finprod [simp] + +lemma id_ring_hom [simp]: + "id \ ring_hom R R" + by (auto intro!: ring_hom_memI) + end diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/Coset.thy --- a/src/HOL/Algebra/Coset.thy Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/Coset.thy Wed Apr 30 10:01:35 2003 +0200 @@ -10,27 +10,27 @@ declare (in group) l_inv [simp] r_inv [simp] constdefs - r_coset :: "[('a,'b) group_scheme,'a set, 'a] => 'a set" + r_coset :: "[('a,'b) monoid_scheme,'a set, 'a] => 'a set" "r_coset G H a == (% x. (mult G) x a) ` H" - l_coset :: "[('a,'b) group_scheme, 'a, 'a set] => 'a set" + l_coset :: "[('a,'b) monoid_scheme, 'a, 'a set] => 'a set" "l_coset G a H == (% x. (mult G) a x) ` H" - rcosets :: "[('a,'b) group_scheme,'a set] => ('a set)set" + rcosets :: "[('a,'b) monoid_scheme,'a set] => ('a set)set" "rcosets G H == r_coset G H ` (carrier G)" - set_mult :: "[('a,'b) group_scheme,'a set,'a set] => 'a set" + set_mult :: "[('a,'b) monoid_scheme,'a set,'a set] => 'a set" "set_mult G H K == (%(x,y). (mult G) x y) ` (H \ K)" - set_inv :: "[('a,'b) group_scheme,'a set] => 'a set" + set_inv :: "[('a,'b) monoid_scheme,'a set] => 'a set" "set_inv G H == (m_inv G) ` H" - normal :: "['a set, ('a,'b) group_scheme] => bool" (infixl "<|" 60) + normal :: "['a set, ('a,'b) monoid_scheme] => bool" (infixl "<|" 60) "normal H G == subgroup H G & (\x \ carrier G. r_coset G H x = l_coset G x H)" syntax (xsymbols) - normal :: "['a set, ('a,'b) group_scheme] => bool" (infixl "\" 60) + normal :: "['a set, ('a,'b) monoid_scheme] => bool" (infixl "\" 60) locale coset = group G + fixes rcos :: "['a set, 'a] => 'a set" (infixl "#>" 60) @@ -153,7 +153,7 @@ subsection{*normal subgroups*} (*???????????????? -text{*Allows use of theorems proved in the locale coset*} +text "Allows use of theorems proved in the locale coset" lemma subgroup_imp_coset: "subgroup H G ==> coset G" apply (drule subgroup_imp_group) apply (simp add: group_def coset_def) @@ -406,13 +406,13 @@ subsection {*Factorization of a Group*} constdefs - FactGroup :: "[('a,'b) group_scheme, 'a set] => ('a set) group" + FactGroup :: "[('a,'b) monoid_scheme, 'a set] => ('a set) monoid" (infixl "Mod" 60) "FactGroup G H == (| carrier = rcosets G H, mult = (%X: rcosets G H. %Y: rcosets G H. set_mult G X Y), - one = H, - m_inv = (%X: rcosets G H. set_inv G X) |)" + one = H (*, + m_inv = (%X: rcosets G H. set_inv G X) *) |)" lemma (in coset) setmult_closed: "[| H <| G; K1 \ rcosets G H; K2 \ rcosets G H |] @@ -482,18 +482,13 @@ "H <| G ==> group (G Mod H)" apply (insert is_coset) apply (simp add: FactGroup_def) -apply (rule group.intro) - apply (rule magma.intro) - apply (simp add: coset.setmult_closed) - apply (rule semigroup_axioms.intro) +apply (rule groupI) + apply (simp add: coset.setmult_closed) + apply (simp add: normal_imp_subgroup subgroup_in_rcosets) apply (simp add: restrictI coset.setmult_closed coset.setrcos_assoc) - apply (rule l_one.intro) - apply (simp add: normal_imp_subgroup subgroup_in_rcosets) apply (simp add: normal_imp_subgroup subgroup_in_rcosets coset.setrcos_mult_eq) -apply (rule group_axioms.intro) - apply (simp add: restrictI setinv_closed) -apply (simp add: setinv_closed coset.setrcos_inv_mult_group_eq) +apply (auto dest: coset.setrcos_inv_mult_group_eq simp add: setinv_closed) done (*???????????????? diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/FiniteProduct.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Algebra/FiniteProduct.thy Wed Apr 30 10:01:35 2003 +0200 @@ -0,0 +1,483 @@ +(* Title: Product Operator for Commutative Monoids + ID: $Id$ + Author: Clemens Ballarin, started 19 November 2002 + +This file is largely based on HOL/Finite_Set.thy. +*) + +header {* Product Operator *} + +theory FiniteProduct = Group: + +(* Instantiation of LC from Finite_Set.thy is not possible, + because here we have explicit typing rules like x : carrier G. + We introduce an explicit argument for the domain D *) + +consts + foldSetD :: "['a set, 'b => 'a => 'a, 'a] => ('b set * 'a) set" + +inductive "foldSetD D f e" + intros + emptyI [intro]: "e : D ==> ({}, e) : foldSetD D f e" + insertI [intro]: "[| x ~: A; f x y : D; (A, y) : foldSetD D f e |] ==> + (insert x A, f x y) : foldSetD D f e" + +inductive_cases empty_foldSetDE [elim!]: "({}, x) : foldSetD D f e" + +constdefs + foldD :: "['a set, 'b => 'a => 'a, 'a, 'b set] => 'a" + "foldD D f e A == THE x. (A, x) : foldSetD D f e" + +lemma foldSetD_closed: + "[| (A, z) : foldSetD D f e ; e : D; !!x y. [| x : A; y : D |] ==> f x y : D + |] ==> z : D"; + by (erule foldSetD.elims) auto + +lemma Diff1_foldSetD: + "[| (A - {x}, y) : foldSetD D f e; x : A; f x y : D |] ==> + (A, f x y) : foldSetD D f e" + apply (erule insert_Diff [THEN subst], rule foldSetD.intros) + apply auto + done + +lemma foldSetD_imp_finite [simp]: "(A, x) : foldSetD D f e ==> finite A" + by (induct set: foldSetD) auto + +lemma finite_imp_foldSetD: + "[| finite A; e : D; !!x y. [| x : A; y : D |] ==> f x y : D |] ==> + EX x. (A, x) : foldSetD D f e" +proof (induct set: Finites) + case empty then show ?case by auto +next + case (insert F x) + then obtain y where y: "(F, y) : foldSetD D f e" by auto + with insert have "y : D" by (auto dest: foldSetD_closed) + with y and insert have "(insert x F, f x y) : foldSetD D f e" + by (intro foldSetD.intros) auto + then show ?case .. +qed + +subsection {* Left-commutative operations *} + +locale LCD = + fixes B :: "'b set" + and D :: "'a set" + and f :: "'b => 'a => 'a" (infixl "\" 70) + assumes left_commute: + "[| x : B; y : B; z : D |] ==> x \ (y \ z) = y \ (x \ z)" + and f_closed [simp, intro!]: "!!x y. [| x : B; y : D |] ==> f x y : D" + +lemma (in LCD) foldSetD_closed [dest]: + "(A, z) : foldSetD D f e ==> z : D"; + by (erule foldSetD.elims) auto + +lemma (in LCD) Diff1_foldSetD: + "[| (A - {x}, y) : foldSetD D f e; x : A; A <= B |] ==> + (A, f x y) : foldSetD D f e" + apply (subgoal_tac "x : B") + prefer 2 apply fast + apply (erule insert_Diff [THEN subst], rule foldSetD.intros) + apply auto + done + +lemma (in LCD) foldSetD_imp_finite [simp]: + "(A, x) : foldSetD D f e ==> finite A" + by (induct set: foldSetD) auto + +lemma (in LCD) finite_imp_foldSetD: + "[| finite A; A <= B; e : D |] ==> EX x. (A, x) : foldSetD D f e" +proof (induct set: Finites) + case empty then show ?case by auto +next + case (insert F x) + then obtain y where y: "(F, y) : foldSetD D f e" by auto + with insert have "y : D" by auto + with y and insert have "(insert x F, f x y) : foldSetD D f e" + by (intro foldSetD.intros) auto + then show ?case .. +qed + +lemma (in LCD) foldSetD_determ_aux: + "e : D ==> ALL A x. A <= B & card A < n --> (A, x) : foldSetD D f e --> + (ALL y. (A, y) : foldSetD D f e --> y = x)" + apply (induct n) + apply (auto simp add: less_Suc_eq) (* slow *) + apply (erule foldSetD.cases) + apply blast + apply (erule foldSetD.cases) + apply blast + apply clarify + txt {* force simplification of @{text "card A < card (insert ...)"}. *} + apply (erule rev_mp) + apply (simp add: less_Suc_eq_le) + apply (rule impI) + apply (rename_tac Aa xa ya Ab xb yb, case_tac "xa = xb") + apply (subgoal_tac "Aa = Ab") + prefer 2 apply (blast elim!: equalityE) + apply blast + txt {* case @{prop "xa \ xb"}. *} + apply (subgoal_tac "Aa - {xb} = Ab - {xa} & xb : Aa & xa : Ab") + prefer 2 apply (blast elim!: equalityE) + apply clarify + apply (subgoal_tac "Aa = insert xb Ab - {xa}") + prefer 2 apply blast + apply (subgoal_tac "card Aa <= card Ab") + prefer 2 + apply (rule Suc_le_mono [THEN subst]) + apply (simp add: card_Suc_Diff1) + apply (rule_tac A1 = "Aa - {xb}" in finite_imp_foldSetD [THEN exE]) + apply (blast intro: foldSetD_imp_finite finite_Diff) + apply best + apply assumption + apply (frule (1) Diff1_foldSetD) + apply best + apply (subgoal_tac "ya = f xb x") + prefer 2 + apply (subgoal_tac "Aa <= B") + prefer 2 apply best (* slow *) + apply (blast del: equalityCE) + apply (subgoal_tac "(Ab - {xa}, x) : foldSetD D f e") + prefer 2 apply simp + apply (subgoal_tac "yb = f xa x") + prefer 2 + apply (blast del: equalityCE dest: Diff1_foldSetD) + apply (simp (no_asm_simp)) + apply (rule left_commute) + apply assumption + apply best (* slow *) + apply best + done + +lemma (in LCD) foldSetD_determ: + "[| (A, x) : foldSetD D f e; (A, y) : foldSetD D f e; e : D; A <= B |] + ==> y = x" + by (blast intro: foldSetD_determ_aux [rule_format]) + +lemma (in LCD) foldD_equality: + "[| (A, y) : foldSetD D f e; e : D; A <= B |] ==> foldD D f e A = y" + by (unfold foldD_def) (blast intro: foldSetD_determ) + +lemma foldD_empty [simp]: + "e : D ==> foldD D f e {} = e" + by (unfold foldD_def) blast + +lemma (in LCD) foldD_insert_aux: + "[| x ~: A; x : B; e : D; A <= B |] ==> + ((insert x A, v) : foldSetD D f e) = + (EX y. (A, y) : foldSetD D f e & v = f x y)" + apply auto + apply (rule_tac A1 = A in finite_imp_foldSetD [THEN exE]) + apply (fastsimp dest: foldSetD_imp_finite) + apply assumption + apply assumption + apply (blast intro: foldSetD_determ) + done + +lemma (in LCD) foldD_insert: + "[| finite A; x ~: A; x : B; e : D; A <= B |] ==> + foldD D f e (insert x A) = f x (foldD D f e A)" + apply (unfold foldD_def) + apply (simp add: foldD_insert_aux) + apply (rule the_equality) + apply (auto intro: finite_imp_foldSetD + cong add: conj_cong simp add: foldD_def [symmetric] foldD_equality) + done + +lemma (in LCD) foldD_closed [simp]: + "[| finite A; e : D; A <= B |] ==> foldD D f e A : D" +proof (induct set: Finites) + case empty then show ?case by (simp add: foldD_empty) +next + case insert then show ?case by (simp add: foldD_insert) +qed + +lemma (in LCD) foldD_commute: + "[| finite A; x : B; e : D; A <= B |] ==> + f x (foldD D f e A) = foldD D f (f x e) A" + apply (induct set: Finites) + apply simp + apply (auto simp add: left_commute foldD_insert) + done + +lemma Int_mono2: + "[| A <= C; B <= C |] ==> A Int B <= C" + by blast + +lemma (in LCD) foldD_nest_Un_Int: + "[| finite A; finite C; e : D; A <= B; C <= B |] ==> + foldD D f (foldD D f e C) A = foldD D f (foldD D f e (A Int C)) (A Un C)" + apply (induct set: Finites) + apply simp + apply (simp add: foldD_insert foldD_commute Int_insert_left insert_absorb + Int_mono2 Un_subset_iff) + done + +lemma (in LCD) foldD_nest_Un_disjoint: + "[| finite A; finite B; A Int B = {}; e : D; A <= B; C <= B |] + ==> foldD D f e (A Un B) = foldD D f (foldD D f e B) A" + by (simp add: foldD_nest_Un_Int) + +-- {* Delete rules to do with @{text foldSetD} relation. *} + +declare foldSetD_imp_finite [simp del] + empty_foldSetDE [rule del] + foldSetD.intros [rule del] +declare (in LCD) + foldSetD_closed [rule del] + +subsection {* Commutative monoids *} + +text {* + We enter a more restrictive context, with @{text "f :: 'a => 'a => 'a"} + instead of @{text "'b => 'a => 'a"}. +*} + +locale ACeD = + fixes D :: "'a set" + and f :: "'a => 'a => 'a" (infixl "\" 70) + and e :: 'a + assumes ident [simp]: "x : D ==> x \ e = x" + and commute: "[| x : D; y : D |] ==> x \ y = y \ x" + and assoc: "[| x : D; y : D; z : D |] ==> (x \ y) \ z = x \ (y \ z)" + and e_closed [simp]: "e : D" + and f_closed [simp]: "[| x : D; y : D |] ==> x \ y : D" + +lemma (in ACeD) left_commute: + "[| x : D; y : D; z : D |] ==> x \ (y \ z) = y \ (x \ z)" +proof - + assume D: "x : D" "y : D" "z : D" + then have "x \ (y \ z) = (y \ z) \ x" by (simp add: commute) + also from D have "... = y \ (z \ x)" by (simp add: assoc) + also from D have "z \ x = x \ z" by (simp add: commute) + finally show ?thesis . +qed + +lemmas (in ACeD) AC = assoc commute left_commute + +lemma (in ACeD) left_ident [simp]: "x : D ==> e \ x = x" +proof - + assume D: "x : D" + have "x \ e = x" by (rule ident) + with D show ?thesis by (simp add: commute) +qed + +lemma (in ACeD) foldD_Un_Int: + "[| finite A; finite B; A <= D; B <= D |] ==> + foldD D f e A \ foldD D f e B = + foldD D f e (A Un B) \ foldD D f e (A Int B)" + apply (induct set: Finites) + apply (simp add: left_commute LCD.foldD_closed [OF LCD.intro [of D]]) + apply (simp add: AC insert_absorb Int_insert_left + LCD.foldD_insert [OF LCD.intro [of D]] + LCD.foldD_closed [OF LCD.intro [of D]] + Int_mono2 Un_subset_iff) + done + +lemma (in ACeD) foldD_Un_disjoint: + "[| finite A; finite B; A Int B = {}; A <= D; B <= D |] ==> + foldD D f e (A Un B) = foldD D f e A \ foldD D f e B" + by (simp add: foldD_Un_Int + left_commute LCD.foldD_closed [OF LCD.intro [of D]] Un_subset_iff) + +subsection {* Products over Finite Sets *} + +constdefs + finprod :: "[('b, 'm) monoid_scheme, 'a => 'b, 'a set] => 'b" + "finprod G f A == if finite A + then foldD (carrier G) (mult G o f) (one G) A + else arbitrary" + +(* TODO: nice syntax for the summation operator inside the locale + like \\ i\A. f i, probably needs hand-coded translation *) + +ML_setup {* + Context.>> (fn thy => (simpset_ref_of thy := + simpset_of thy setsubgoaler asm_full_simp_tac; thy)) +*} + +lemma (in comm_monoid) finprod_empty [simp]: + "finprod G f {} = \" + by (simp add: finprod_def) + +ML_setup {* + Context.>> (fn thy => (simpset_ref_of thy := + simpset_of thy setsubgoaler asm_simp_tac; thy)) +*} + +declare funcsetI [intro] + funcset_mem [dest] + +lemma (in comm_monoid) finprod_insert [simp]: + "[| finite F; a \ F; f \ F -> carrier G; f a \ carrier G |] ==> + finprod G f (insert a F) = f a \ finprod G f F" + apply (rule trans) + apply (simp add: finprod_def) + apply (rule trans) + apply (rule LCD.foldD_insert [OF LCD.intro [of "insert a F"]]) + apply simp + apply (rule m_lcomm) + apply fast + apply fast + apply assumption + apply (fastsimp intro: m_closed) + apply simp+ + apply fast + apply (auto simp add: finprod_def) + done + +lemma (in comm_monoid) finprod_one [simp]: + "finite A ==> finprod G (%i. \) A = \" +proof (induct set: Finites) + case empty show ?case by simp +next + case (insert A a) + have "(%i. \) \ A -> carrier G" by auto + with insert show ?case by simp +qed + +lemma (in comm_monoid) finprod_closed [simp]: + fixes A + assumes fin: "finite A" and f: "f \ A -> carrier G" + shows "finprod G f A \ carrier G" +using fin f +proof induct + case empty show ?case by simp +next + case (insert A a) + then have a: "f a \ carrier G" by fast + from insert have A: "f \ A -> carrier G" by fast + from insert A a show ?case by simp +qed + +lemma funcset_Int_left [simp, intro]: + "[| f \ A -> C; f \ B -> C |] ==> f \ A Int B -> C" + by fast + +lemma funcset_Un_left [iff]: + "(f \ A Un B -> C) = (f \ A -> C & f \ B -> C)" + by fast + +lemma (in comm_monoid) finprod_Un_Int: + "[| finite A; finite B; g \ A -> carrier G; g \ B -> carrier G |] ==> + finprod G g (A Un B) \ finprod G g (A Int B) = + finprod G g A \ finprod G g B" +-- {* The reversed orientation looks more natural, but LOOPS as a simprule! *} +proof (induct set: Finites) + case empty then show ?case by (simp add: finprod_closed) +next + case (insert A a) + then have a: "g a \ carrier G" by fast + from insert have A: "g \ A -> carrier G" by fast + from insert A a show ?case + by (simp add: m_ac Int_insert_left insert_absorb finprod_closed + Int_mono2 Un_subset_iff) +qed + +lemma (in comm_monoid) finprod_Un_disjoint: + "[| finite A; finite B; A Int B = {}; + g \ A -> carrier G; g \ B -> carrier G |] + ==> finprod G g (A Un B) = finprod G g A \ finprod G g B" + apply (subst finprod_Un_Int [symmetric]) + apply (auto simp add: finprod_closed) + done + +lemma (in comm_monoid) finprod_multf: + "[| finite A; f \ A -> carrier G; g \ A -> carrier G |] ==> + finprod G (%x. f x \ g x) A = (finprod G f A \ finprod G g A)" +proof (induct set: Finites) + case empty show ?case by simp +next + case (insert A a) then + have fA: "f : A -> carrier G" by fast + from insert have fa: "f a : carrier G" by fast + from insert have gA: "g : A -> carrier G" by fast + from insert have ga: "g a : carrier G" by fast + from insert have fgA: "(%x. f x \ g x) : A -> carrier G" + by (simp add: Pi_def) + show ?case (* check if all simps are really necessary *) + by (simp add: insert fA fa gA ga fgA m_ac Int_insert_left insert_absorb + Int_mono2 Un_subset_iff) +qed + +lemma (in comm_monoid) finprod_cong': + "[| A = B; g : B -> carrier G; + !!i. i : B ==> f i = g i |] ==> finprod G f A = finprod G g B" +proof - + assume prems: "A = B" "g : B -> carrier G" + "!!i. i : B ==> f i = g i" + show ?thesis + proof (cases "finite B") + case True + then have "!!A. [| A = B; g : B -> carrier G; + !!i. i : B ==> f i = g i |] ==> finprod G f A = finprod G g B" + proof induct + case empty thus ?case by simp + next + case (insert B x) + then have "finprod G f A = finprod G f (insert x B)" by simp + also from insert have "... = f x \ finprod G f B" + proof (intro finprod_insert) + show "finite B" . + next + show "x ~: B" . + next + assume "x ~: B" "!!i. i \ insert x B \ f i = g i" + "g \ insert x B \ carrier G" + thus "f : B -> carrier G" by fastsimp + next + assume "x ~: B" "!!i. i \ insert x B \ f i = g i" + "g \ insert x B \ carrier G" + thus "f x \ carrier G" by fastsimp + qed + also from insert have "... = g x \ finprod G g B" by fastsimp + also from insert have "... = finprod G g (insert x B)" + by (intro finprod_insert [THEN sym]) auto + finally show ?case . + qed + with prems show ?thesis by simp + next + case False with prems show ?thesis by (simp add: finprod_def) + qed +qed + +lemma (in comm_monoid) finprod_cong: + "[| A = B; !!i. i : B ==> f i = g i; + g : B -> carrier G = True |] ==> finprod G f A = finprod G g B" + by (rule finprod_cong') fast+ + +text {*Usually, if this rule causes a failed congruence proof error, + the reason is that the premise @{text "g : B -> carrier G"} cannot be shown. + Adding @{thm [source] Pi_def} to the simpset is often useful. + For this reason, @{thm [source] comm_monoid.finprod_cong} + is not added to the simpset by default. +*} + +declare funcsetI [rule del] + funcset_mem [rule del] + +lemma (in comm_monoid) finprod_0 [simp]: + "f : {0::nat} -> carrier G ==> finprod G f {..0} = f 0" +by (simp add: Pi_def) + +lemma (in comm_monoid) finprod_Suc [simp]: + "f : {..Suc n} -> carrier G ==> + finprod G f {..Suc n} = (f (Suc n) \ finprod G f {..n})" +by (simp add: Pi_def atMost_Suc) + +lemma (in comm_monoid) finprod_Suc2: + "f : {..Suc n} -> carrier G ==> + finprod G f {..Suc n} = (finprod G (%i. f (Suc i)) {..n} \ f 0)" +proof (induct n) + case 0 thus ?case by (simp add: Pi_def) +next + case Suc thus ?case by (simp add: m_assoc Pi_def) +qed + +lemma (in comm_monoid) finprod_mult [simp]: + "[| f : {..n} -> carrier G; g : {..n} -> carrier G |] ==> + finprod G (%i. f i \ g i) {..n::nat} = + finprod G f {..n} \ finprod G g {..n}" + by (induct n) (simp_all add: m_ac Pi_def) + +end + diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/Group.thy --- a/src/HOL/Algebra/Group.thy Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/Group.thy Wed Apr 30 10:01:35 2003 +0200 @@ -6,18 +6,23 @@ Based on work by Florian Kammueller, L C Paulson and Markus Wenzel. *) -header {* Algebraic Structures up to Abelian Groups *} +header {* Algebraic Structures up to Commutative Groups *} theory Group = FuncSet: +axclass number < type + +instance nat :: number .. +instance int :: number .. + +section {* From Magmas to Groups *} + text {* Definitions follow Jacobson, Basic Algebra I, Freeman, 1985; with the exception of \emph{magma} which, following Bourbaki, is a set together with a binary, closed operation. *} -section {* From Magmas to Groups *} - subsection {* Definitions *} record 'a semigroup = @@ -27,8 +32,23 @@ record 'a monoid = "'a semigroup" + one :: 'a ("\\") -record 'a group = "'a monoid" + - m_inv :: "'a => 'a" ("inv\ _" [81] 80) +constdefs + m_inv :: "[('a, 'm) monoid_scheme, 'a] => 'a" ("inv\ _" [81] 80) + "m_inv G x == (THE y. y \ carrier G & + mult G x y = one G & mult G y x = one G)" + + Units :: "('a, 'm) monoid_scheme => 'a set" + "Units G == {y. y \ carrier G & + (EX x : carrier G. mult G x y = one G & mult G y x = one G)}" + +consts + pow :: "[('a, 'm) monoid_scheme, 'a, 'b::number] => 'a" (infixr "'(^')\" 75) + +defs (overloaded) + nat_pow_def: "pow G a n == nat_rec (one G) (%u b. mult G b a) n" + int_pow_def: "pow G a z == + let p = nat_rec (one G) (%u b. mult G b a) + in if neg z then m_inv G (p (nat (-z))) else p (nat z)" locale magma = struct G + assumes m_closed [intro, simp]: @@ -37,32 +57,237 @@ locale semigroup = magma + assumes m_assoc: "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> - (x \ y) \ z = x \ (y \ z)" + (x \ y) \ z = x \ (y \ z)" -locale l_one = struct G + +locale monoid = semigroup + assumes one_closed [intro, simp]: "\ \ carrier G" and l_one [simp]: "x \ carrier G ==> \ \ x = x" + and r_one [simp]: "x \ carrier G ==> x \ \ = x" -locale group = semigroup + l_one + - assumes inv_closed [intro, simp]: "x \ carrier G ==> inv x \ carrier G" - and l_inv: "x \ carrier G ==> inv x \ x = \" +lemma monoidI: + assumes m_closed: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y \ carrier G" + and one_closed: "one G \ carrier G" + and m_assoc: + "!!x y z. [| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + mult G (mult G x y) z = mult G x (mult G y z)" + and l_one: "!!x. x \ carrier G ==> mult G (one G) x = x" + and r_one: "!!x. x \ carrier G ==> mult G x (one G) = x" + shows "monoid G" + by (fast intro!: monoid.intro magma.intro semigroup_axioms.intro + semigroup.intro monoid_axioms.intro + intro: prems) + +lemma (in monoid) Units_closed [dest]: + "x \ Units G ==> x \ carrier G" + by (unfold Units_def) fast + +lemma (in monoid) inv_unique: + assumes eq: "y \ x = \" "x \ y' = \" + and G: "x \ carrier G" "y \ carrier G" "y' \ carrier G" + shows "y = y'" +proof - + from G eq have "y = y \ (x \ y')" by simp + also from G have "... = (y \ x) \ y'" by (simp add: m_assoc) + also from G eq have "... = y'" by simp + finally show ?thesis . +qed + +lemma (in monoid) Units_inv_closed [intro, simp]: + "x \ Units G ==> inv x \ carrier G" + apply (unfold Units_def m_inv_def) + apply auto + apply (rule theI2, fast) + apply (fast intro: inv_unique) + apply fast + done + +lemma (in monoid) Units_l_inv: + "x \ Units G ==> inv x \ x = \" + apply (unfold Units_def m_inv_def) + apply auto + apply (rule theI2, fast) + apply (fast intro: inv_unique) + apply fast + done + +lemma (in monoid) Units_r_inv: + "x \ Units G ==> x \ inv x = \" + apply (unfold Units_def m_inv_def) + apply auto + apply (rule theI2, fast) + apply (fast intro: inv_unique) + apply fast + done + +lemma (in monoid) Units_inv_Units [intro, simp]: + "x \ Units G ==> inv x \ Units G" +proof - + assume x: "x \ Units G" + show "inv x \ Units G" + by (auto simp add: Units_def + intro: Units_l_inv Units_r_inv x Units_closed [OF x]) +qed + +lemma (in monoid) Units_l_cancel [simp]: + "[| x \ Units G; y \ carrier G; z \ carrier G |] ==> + (x \ y = x \ z) = (y = z)" +proof + assume eq: "x \ y = x \ z" + and G: "x \ Units G" "y \ carrier G" "z \ carrier G" + then have "(inv x \ x) \ y = (inv x \ x) \ z" + by (simp add: m_assoc Units_closed) + with G show "y = z" by (simp add: Units_l_inv) +next + assume eq: "y = z" + and G: "x \ Units G" "y \ carrier G" "z \ carrier G" + then show "x \ y = x \ z" by simp +qed + +lemma (in monoid) Units_inv_inv [simp]: + "x \ Units G ==> inv (inv x) = x" +proof - + assume x: "x \ Units G" + then have "inv x \ inv (inv x) = inv x \ x" + by (simp add: Units_l_inv Units_r_inv) + with x show ?thesis by (simp add: Units_closed) +qed + +lemma (in monoid) inv_inj_on_Units: + "inj_on (m_inv G) (Units G)" +proof (rule inj_onI) + fix x y + assume G: "x \ Units G" "y \ Units G" and eq: "inv x = inv y" + then have "inv (inv x) = inv (inv y)" by simp + with G show "x = y" by simp +qed + +text {* Power *} + +lemma (in monoid) nat_pow_closed [intro, simp]: + "x \ carrier G ==> x (^) (n::nat) \ carrier G" + by (induct n) (simp_all add: nat_pow_def) + +lemma (in monoid) nat_pow_0 [simp]: + "x (^) (0::nat) = \" + by (simp add: nat_pow_def) + +lemma (in monoid) nat_pow_Suc [simp]: + "x (^) (Suc n) = x (^) n \ x" + by (simp add: nat_pow_def) + +lemma (in monoid) nat_pow_one [simp]: + "\ (^) (n::nat) = \" + by (induct n) simp_all + +lemma (in monoid) nat_pow_mult: + "x \ carrier G ==> x (^) (n::nat) \ x (^) m = x (^) (n + m)" + by (induct m) (simp_all add: m_assoc [THEN sym]) + +lemma (in monoid) nat_pow_pow: + "x \ carrier G ==> (x (^) n) (^) m = x (^) (n * m::nat)" + by (induct m) (simp, simp add: nat_pow_mult add_commute) + +text {* + A group is a monoid all of whose elements are invertible. +*} + +locale group = monoid + + assumes Units: "carrier G <= Units G" + +theorem groupI: + assumes m_closed [simp]: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y \ carrier G" + and one_closed [simp]: "one G \ carrier G" + and m_assoc: + "!!x y z. [| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + mult G (mult G x y) z = mult G x (mult G y z)" + and l_one [simp]: "!!x. x \ carrier G ==> mult G (one G) x = x" + and l_inv_ex: "!!x. x \ carrier G ==> EX y : carrier G. mult G y x = one G" + shows "group G" +proof - + have l_cancel [simp]: + "!!x y z. [| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + (mult G x y = mult G x z) = (y = z)" + proof + fix x y z + assume eq: "mult G x y = mult G x z" + and G: "x \ carrier G" "y \ carrier G" "z \ carrier G" + with l_inv_ex obtain x_inv where xG: "x_inv \ carrier G" + and l_inv: "mult G x_inv x = one G" by fast + from G eq xG have "mult G (mult G x_inv x) y = mult G (mult G x_inv x) z" + by (simp add: m_assoc) + with G show "y = z" by (simp add: l_inv) + next + fix x y z + assume eq: "y = z" + and G: "x \ carrier G" "y \ carrier G" "z \ carrier G" + then show "mult G x y = mult G x z" by simp + qed + have r_one: + "!!x. x \ carrier G ==> mult G x (one G) = x" + proof - + fix x + assume x: "x \ carrier G" + with l_inv_ex obtain x_inv where xG: "x_inv \ carrier G" + and l_inv: "mult G x_inv x = one G" by fast + from x xG have "mult G x_inv (mult G x (one G)) = mult G x_inv x" + by (simp add: m_assoc [symmetric] l_inv) + with x xG show "mult G x (one G) = x" by simp + qed + have inv_ex: + "!!x. x \ carrier G ==> EX y : carrier G. mult G y x = one G & + mult G x y = one G" + proof - + fix x + assume x: "x \ carrier G" + with l_inv_ex obtain y where y: "y \ carrier G" + and l_inv: "mult G y x = one G" by fast + from x y have "mult G y (mult G x y) = mult G y (one G)" + by (simp add: m_assoc [symmetric] l_inv r_one) + with x y have r_inv: "mult G x y = one G" + by simp + from x y show "EX y : carrier G. mult G y x = one G & + mult G x y = one G" + by (fast intro: l_inv r_inv) + qed + then have carrier_subset_Units: "carrier G <= Units G" + by (unfold Units_def) fast + show ?thesis + by (fast intro!: group.intro magma.intro semigroup_axioms.intro + semigroup.intro monoid_axioms.intro group_axioms.intro + carrier_subset_Units intro: prems r_one) +qed + +lemma (in monoid) monoid_groupI: + assumes l_inv_ex: + "!!x. x \ carrier G ==> EX y : carrier G. mult G y x = one G" + shows "group G" + by (rule groupI) (auto intro: m_assoc l_inv_ex) + +lemma (in group) Units_eq [simp]: + "Units G = carrier G" +proof + show "Units G <= carrier G" by fast +next + show "carrier G <= Units G" by (rule Units) +qed + +lemma (in group) inv_closed [intro, simp]: + "x \ carrier G ==> inv x \ carrier G" + using Units_inv_closed by simp + +lemma (in group) l_inv: + "x \ carrier G ==> inv x \ x = \" + using Units_l_inv by simp subsection {* Cancellation Laws and Basic Properties *} lemma (in group) l_cancel [simp]: "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> (x \ y = x \ z) = (y = z)" -proof - assume eq: "x \ y = x \ z" - and G: "x \ carrier G" "y \ carrier G" "z \ carrier G" - then have "(inv x \ x) \ y = (inv x \ x) \ z" by (simp add: m_assoc) - with G show "y = z" by (simp add: l_inv) -next - assume eq: "y = z" - and G: "x \ carrier G" "y \ carrier G" "z \ carrier G" - then show "x \ y = x \ z" by simp -qed - + using Units_l_inv by simp +(* lemma (in group) r_one [simp]: "x \ carrier G ==> x \ \ = x" proof - @@ -71,7 +296,7 @@ by (simp add: m_assoc [symmetric] l_inv) with x show ?thesis by simp qed - +*) lemma (in group) r_inv: "x \ carrier G ==> x \ inv x = \" proof - @@ -106,11 +331,11 @@ lemma (in group) inv_inv [simp]: "x \ carrier G ==> inv (inv x) = x" -proof - - assume x: "x \ carrier G" - then have "inv x \ inv (inv x) = inv x \ x" by (simp add: l_inv r_inv) - with x show ?thesis by simp -qed + using Units_inv_inv by simp + +lemma (in group) inv_inj: + "inj_on (m_inv G) (carrier G)" + using inv_inj_on_Units by simp lemma (in group) inv_mult_group: "[| x \ carrier G; y \ carrier G |] ==> inv (x \ y) = inv y \ inv x" @@ -121,6 +346,20 @@ with G show ?thesis by simp qed +text {* Power *} + +lemma (in group) int_pow_def2: + "a (^) (z::int) = (if neg z then inv (a (^) (nat (-z))) else a (^) (nat z))" + by (simp add: int_pow_def nat_pow_def Let_def) + +lemma (in group) int_pow_0 [simp]: + "x (^) (0::int) = \" + by (simp add: int_pow_def2) + +lemma (in group) int_pow_one [simp]: + "\ (^) (z::int) = \" + by (simp add: int_pow_def2) + subsection {* Substructures *} locale submagma = var H + struct G + @@ -128,7 +367,7 @@ and m_closed [intro, simp]: "[| x \ H; y \ H |] ==> x \ y \ H" declare (in submagma) magma.intro [intro] semigroup.intro [intro] - + semigroup_axioms.intro [intro] (* alternative definition of submagma @@ -167,21 +406,21 @@ and m_inv_closed [intro, simp]: "x \ H ==> inv x \ H" declare (in subgroup) group.intro [intro] - +(* lemma (in subgroup) l_oneI [intro]: includes l_one G shows "l_one (G(| carrier := H |))" by rule simp_all - +*) lemma (in subgroup) group_axiomsI [intro]: includes group G shows "group_axioms (G(| carrier := H |))" - by rule (simp_all add: l_inv) + by rule (auto intro: l_inv r_inv simp add: Units_def) lemma (in subgroup) groupI [intro]: includes group G shows "group (G(| carrier := H |))" - using prems by fast + by (rule groupI) (auto intro: m_assoc l_inv) text {* Since @{term H} is nonempty, it contains some element @{term x}. Since @@ -223,8 +462,8 @@ declare magma.m_closed [simp] -declare l_one.one_closed [iff] group.inv_closed [simp] - l_one.l_one [simp] group.r_one [simp] group.inv_inv [simp] +declare monoid.one_closed [iff] group.inv_closed [simp] + monoid.l_one [simp] monoid.r_one [simp] group.inv_inv [simp] lemma subgroup_nonempty: "~ subgroup {} G" @@ -241,6 +480,11 @@ with subgroup_nonempty show ?thesis by contradiction qed +(* +lemma (in monoid) Units_subgroup: + "subgroup (Units G) G" +*) + subsection {* Direct Products *} constdefs @@ -251,13 +495,13 @@ "G \\<^sub>s H == (| carrier = carrier G \ carrier H, mult = (%(xg, xh) (yg, yh). (mult G xg yg, mult H xh yh)) |)" - DirProdMonoid :: + DirProdGroup :: "[('a, 'm) monoid_scheme, ('b, 'n) monoid_scheme] => ('a \ 'b) monoid" - (infixr "\\<^sub>m" 80) - "G \\<^sub>m H == (| carrier = carrier (G \\<^sub>s H), + (infixr "\\<^sub>g" 80) + "G \\<^sub>g H == (| carrier = carrier (G \\<^sub>s H), mult = mult (G \\<^sub>s H), one = (one G, one H) |)" - +(* DirProdGroup :: "[('a, 'm) group_scheme, ('b, 'n) group_scheme] => ('a \ 'b) group" (infixr "\\<^sub>g" 80) @@ -265,6 +509,7 @@ mult = mult (G \\<^sub>m H), one = one (G \\<^sub>m H), m_inv = (%(g, h). (m_inv G g, m_inv H h)) |)" +*) lemma DirProdSemigroup_magma: includes magma G + magma H @@ -287,13 +532,13 @@ includes magma G + magma H shows "magma (G \\<^sub>g H)" by rule - (auto simp add: DirProdGroup_def DirProdMonoid_def DirProdSemigroup_def) + (auto simp add: DirProdGroup_def DirProdSemigroup_def) lemma DirProdGroup_semigroup_axioms: includes semigroup G + semigroup H shows "semigroup_axioms (G \\<^sub>g H)" by rule - (auto simp add: DirProdGroup_def DirProdMonoid_def DirProdSemigroup_def + (auto simp add: DirProdGroup_def DirProdSemigroup_def G.m_assoc H.m_assoc) lemma DirProdGroup_semigroup: @@ -308,11 +553,9 @@ lemma DirProdGroup_group: includes group G + group H shows "group (G \\<^sub>g H)" -by rule - (auto intro: magma.intro l_one.intro - semigroup_axioms.intro group_axioms.intro - simp add: DirProdGroup_def DirProdMonoid_def DirProdSemigroup_def - G.m_assoc H.m_assoc G.l_inv H.l_inv) + by (rule groupI) + (auto intro: G.m_assoc H.m_assoc G.l_inv H.l_inv + simp add: DirProdGroup_def DirProdSemigroup_def) subsection {* Homomorphisms *} @@ -376,14 +619,20 @@ with x show ?thesis by simp qed -section {* Abelian Structures *} +section {* Commutative Structures *} + +text {* + Naming convention: multiplicative structures that are commutative + are called \emph{commutative}, additive structures are called + \emph{Abelian}. +*} subsection {* Definition *} -locale abelian_semigroup = semigroup + +locale comm_semigroup = semigroup + assumes m_comm: "[| x \ carrier G; y \ carrier G |] ==> x \ y = y \ x" -lemma (in abelian_semigroup) m_lcomm: +lemma (in comm_semigroup) m_lcomm: "[| x \ carrier G; y \ carrier G; z \ carrier G |] ==> x \ (y \ z) = y \ (x \ z)" proof - @@ -394,11 +643,33 @@ finally show ?thesis . qed -lemmas (in abelian_semigroup) ac = m_assoc m_comm m_lcomm +lemmas (in comm_semigroup) m_ac = m_assoc m_comm m_lcomm + +locale comm_monoid = comm_semigroup + monoid -locale abelian_monoid = abelian_semigroup + l_one +lemma comm_monoidI: + assumes m_closed: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y \ carrier G" + and one_closed: "one G \ carrier G" + and m_assoc: + "!!x y z. [| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + mult G (mult G x y) z = mult G x (mult G y z)" + and l_one: "!!x. x \ carrier G ==> mult G (one G) x = x" + and m_comm: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y = mult G y x" + shows "comm_monoid G" + using l_one + by (auto intro!: comm_monoid.intro magma.intro semigroup_axioms.intro + comm_semigroup_axioms.intro monoid_axioms.intro + intro: prems simp: m_closed one_closed m_comm) -lemma (in abelian_monoid) l_one [simp]: +lemma (in monoid) monoid_comm_monoidI: + assumes m_comm: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y = mult G y x" + shows "comm_monoid G" + by (rule comm_monoidI) (auto intro: m_assoc m_comm) +(* +lemma (in comm_monoid) r_one [simp]: "x \ carrier G ==> x \ \ = x" proof - assume G: "x \ carrier G" @@ -406,11 +677,38 @@ also from G have "... = x" by simp finally show ?thesis . qed +*) -locale abelian_group = abelian_monoid + group +lemma (in comm_monoid) nat_pow_distr: + "[| x \ carrier G; y \ carrier G |] ==> + (x \ y) (^) (n::nat) = x (^) n \ y (^) n" + by (induct n) (simp, simp add: m_ac) + +locale comm_group = comm_monoid + group + +lemma (in group) group_comm_groupI: + assumes m_comm: "!!x y. [| x \ carrier G; y \ carrier G |] ==> + mult G x y = mult G y x" + shows "comm_group G" + by (fast intro: comm_group.intro comm_semigroup_axioms.intro + group.axioms prems) -lemma (in abelian_group) inv_mult: +lemma comm_groupI: + assumes m_closed: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y \ carrier G" + and one_closed: "one G \ carrier G" + and m_assoc: + "!!x y z. [| x \ carrier G; y \ carrier G; z \ carrier G |] ==> + mult G (mult G x y) z = mult G x (mult G y z)" + and m_comm: + "!!x y. [| x \ carrier G; y \ carrier G |] ==> mult G x y = mult G y x" + and l_one: "!!x. x \ carrier G ==> mult G (one G) x = x" + and l_inv_ex: "!!x. x \ carrier G ==> EX y : carrier G. mult G y x = one G" + shows "comm_group G" + by (fast intro: group.group_comm_groupI groupI prems) + +lemma (in comm_group) inv_mult: "[| x \ carrier G; y \ carrier G |] ==> inv (x \ y) = inv x \ inv y" - by (simp add: ac inv_mult_group) + by (simp add: m_ac inv_mult_group) end diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/Module.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Algebra/Module.thy Wed Apr 30 10:01:35 2003 +0200 @@ -0,0 +1,161 @@ +(* Title: HOL/Algebra/Module + ID: $Id$ + Author: Clemens Ballarin, started 15 April 2003 + Copyright: Clemens Ballarin +*) + +theory Module = CRing: + +section {* Modules over an Abelian Group *} + +record ('a, 'b) module = "'b ring" + + smult :: "['a, 'b] => 'b" (infixl "\\" 70) + +locale module = cring R + abelian_group M + + assumes smult_closed [simp, intro]: + "[| a \ carrier R; x \ carrier M |] ==> a \\<^sub>2 x \ carrier M" + and smult_l_distr: + "[| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + (a \ b) \\<^sub>2 x = a \\<^sub>2 x \\<^sub>2 b \\<^sub>2 x" + and smult_r_distr: + "[| a \ carrier R; x \ carrier M; y \ carrier M |] ==> + a \\<^sub>2 (x \\<^sub>2 y) = a \\<^sub>2 x \\<^sub>2 a \\<^sub>2 y" + and smult_assoc1: + "[| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + (a \ b) \\<^sub>2 x = a \\<^sub>2 (b \\<^sub>2 x)" + and smult_one [simp]: + "x \ carrier M ==> \ \\<^sub>2 x = x" + +locale algebra = module R M + cring M + + assumes smult_assoc2: + "[| a \ carrier R; x \ carrier M; y \ carrier M |] ==> + (a \\<^sub>2 x) \\<^sub>2 y = a \\<^sub>2 (x \\<^sub>2 y)" + +lemma moduleI: + assumes cring: "cring R" + and abelian_group: "abelian_group M" + and smult_closed: + "!!a x. [| a \ carrier R; x \ carrier M |] ==> smult M a x \ carrier M" + and smult_l_distr: + "!!a b x. [| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + smult M (add R a b) x = add M (smult M a x) (smult M b x)" + and smult_r_distr: + "!!a x y. [| a \ carrier R; x \ carrier M; y \ carrier M |] ==> + smult M a (add M x y) = add M (smult M a x) (smult M a y)" + and smult_assoc1: + "!!a b x. [| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + smult M (mult R a b) x = smult M a (smult M b x)" + and smult_one: + "!!x. x \ carrier M ==> smult M (one R) x = x" + shows "module R M" + by (auto intro: module.intro cring.axioms abelian_group.axioms + module_axioms.intro prems) + +lemma algebraI: + assumes R_cring: "cring R" + and M_cring: "cring M" + and smult_closed: + "!!a x. [| a \ carrier R; x \ carrier M |] ==> smult M a x \ carrier M" + and smult_l_distr: + "!!a b x. [| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + smult M (add R a b) x = add M (smult M a x) (smult M b x)" + and smult_r_distr: + "!!a x y. [| a \ carrier R; x \ carrier M; y \ carrier M |] ==> + smult M a (add M x y) = add M (smult M a x) (smult M a y)" + and smult_assoc1: + "!!a b x. [| a \ carrier R; b \ carrier R; x \ carrier M |] ==> + smult M (mult R a b) x = smult M a (smult M b x)" + and smult_one: + "!!x. x \ carrier M ==> smult M (one R) x = x" + and smult_assoc2: + "!!a x y. [| a \ carrier R; x \ carrier M; y \ carrier M |] ==> + mult M (smult M a x) y = smult M a (mult M x y)" + shows "algebra R M" + by (auto intro!: algebra.intro algebra_axioms.intro cring.axioms + module_axioms.intro prems) + +lemma (in algebra) R_cring: + "cring R" + by (rule cring.intro) assumption+ + +lemma (in algebra) M_cring: + "cring M" + by (rule cring.intro) assumption+ + +lemma (in algebra) module: + "module R M" + by (auto intro: moduleI R_cring is_abelian_group + smult_l_distr smult_r_distr smult_assoc1) + +subsection {* Basic Properties of Algebras *} + +lemma (in algebra) smult_l_null [simp]: + "x \ carrier M ==> \ \\<^sub>2 x = \\<^sub>2" +proof - + assume M: "x \ carrier M" + note facts = M smult_closed + from facts have "\ \\<^sub>2 x = (\ \\<^sub>2 x \\<^sub>2 \ \\<^sub>2 x) \\<^sub>2 \\<^sub>2 (\ \\<^sub>2 x)" by algebra + also from M have "... = (\ \ \) \\<^sub>2 x \\<^sub>2 \\<^sub>2 (\ \\<^sub>2 x)" + by (simp add: smult_l_distr del: R.l_zero R.r_zero) + also from facts have "... = \\<^sub>2" by algebra + finally show ?thesis . +qed + +lemma (in algebra) smult_r_null [simp]: + "a \ carrier R ==> a \\<^sub>2 \\<^sub>2 = \\<^sub>2"; +proof - + assume R: "a \ carrier R" + note facts = R smult_closed + from facts have "a \\<^sub>2 \\<^sub>2 = (a \\<^sub>2 \\<^sub>2 \\<^sub>2 a \\<^sub>2 \\<^sub>2) \\<^sub>2 \\<^sub>2 (a \\<^sub>2 \\<^sub>2)" + by algebra + also from R have "... = a \\<^sub>2 (\\<^sub>2 \\<^sub>2 \\<^sub>2) \\<^sub>2 \\<^sub>2 (a \\<^sub>2 \\<^sub>2)" + by (simp add: smult_r_distr del: M.l_zero M.r_zero) + also from facts have "... = \\<^sub>2" by algebra + finally show ?thesis . +qed + +lemma (in algebra) smult_l_minus: + "[| a \ carrier R; x \ carrier M |] ==> (\a) \\<^sub>2 x = \\<^sub>2 (a \\<^sub>2 x)" +proof - + assume RM: "a \ carrier R" "x \ carrier M" + note facts = RM smult_closed + from facts have "(\a) \\<^sub>2 x = (\a \\<^sub>2 x \\<^sub>2 a \\<^sub>2 x) \\<^sub>2 \\<^sub>2(a \\<^sub>2 x)" by algebra + also from RM have "... = (\a \ a) \\<^sub>2 x \\<^sub>2 \\<^sub>2(a \\<^sub>2 x)" + by (simp add: smult_l_distr) + also from facts smult_l_null have "... = \\<^sub>2(a \\<^sub>2 x)" by algebra + finally show ?thesis . +qed + +lemma (in algebra) smult_r_minus: + "[| a \ carrier R; x \ carrier M |] ==> a \\<^sub>2 (\\<^sub>2x) = \\<^sub>2 (a \\<^sub>2 x)" +proof - + assume RM: "a \ carrier R" "x \ carrier M" + note facts = RM smult_closed + from facts have "a \\<^sub>2 (\\<^sub>2x) = (a \\<^sub>2 \\<^sub>2x \\<^sub>2 a \\<^sub>2 x) \\<^sub>2 \\<^sub>2(a \\<^sub>2 x)" + by algebra + also from RM have "... = a \\<^sub>2 (\\<^sub>2x \\<^sub>2 x) \\<^sub>2 \\<^sub>2(a \\<^sub>2 x)" + by (simp add: smult_r_distr) + also from facts smult_r_null have "... = \\<^sub>2(a \\<^sub>2 x)" by algebra + finally show ?thesis . +qed + +subsection {* Every Abelian Group is a $\mathbb{Z}$-module *} + +text {* Not finished. *} + +constdefs + INTEG :: "int ring" + "INTEG == (| carrier = UNIV, mult = op *, one = 1, zero = 0, add = op + |)" + +(* + INTEG_MODULE :: "('a, 'm) ring_scheme => (int, 'a) module" + "INTEG_MODULE R == (| carrier = carrier R, mult = mult R, one = one R, + zero = zero R, add = add R, smult = (%n. %x:carrier R. ... ) |)" +*) + +lemma cring_INTEG: + "cring INTEG" + by (unfold INTEG_def) (auto intro!: cringI abelian_groupI comm_monoidI + zadd_zminus_inverse2 zadd_zmult_distrib) + +end diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/ROOT.ML --- a/src/HOL/Algebra/ROOT.ML Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/ROOT.ML Wed Apr 30 10:01:35 2003 +0200 @@ -1,9 +1,16 @@ (* - Polynomials + The Isabelle Algebraic Library $Id$ Author: Clemens Ballarin, started 24 September 1999 *) +(* New development, based on explicit structures *) + +use_thy "Sylow"; (* Groups *) +(* use_thy "UnivPoly"; *) (* Rings and polynomials *) + +(* Old development, based on axiomatic type classes. + Will be withdrawn in future. *) + with_path "abstract" time_use_thy "Abstract"; (*The ring theory*) with_path "poly" time_use_thy "Polynomial"; (*The full theory*) -use_thy "Sylow"; diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/Summation.thy --- a/src/HOL/Algebra/Summation.thy Tue Apr 29 12:36:49 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,500 +0,0 @@ -(* Title: Summation Operator for Abelian Groups - ID: $Id$ - Author: Clemens Ballarin, started 19 November 2002 - -This file is largely based on HOL/Finite_Set.thy. -*) - -header {* Summation Operator *} - -theory Summation = Group: - -(* Instantiation of LC from Finite_Set.thy is not possible, - because here we have explicit typing rules like x : carrier G. - We introduce an explicit argument for the domain D *) - -consts - foldSetD :: "['a set, 'b => 'a => 'a, 'a] => ('b set * 'a) set" - -inductive "foldSetD D f e" - intros - emptyI [intro]: "e : D ==> ({}, e) : foldSetD D f e" - insertI [intro]: "[| x ~: A; f x y : D; (A, y) : foldSetD D f e |] ==> - (insert x A, f x y) : foldSetD D f e" - -inductive_cases empty_foldSetDE [elim!]: "({}, x) : foldSetD D f e" - -constdefs - foldD :: "['a set, 'b => 'a => 'a, 'a, 'b set] => 'a" - "foldD D f e A == THE x. (A, x) : foldSetD D f e" - -lemma foldSetD_closed: - "[| (A, z) : foldSetD D f e ; e : D; !!x y. [| x : A; y : D |] ==> f x y : D - |] ==> z : D"; - by (erule foldSetD.elims) auto - -lemma Diff1_foldSetD: - "[| (A - {x}, y) : foldSetD D f e; x : A; f x y : D |] ==> - (A, f x y) : foldSetD D f e" - apply (erule insert_Diff [THEN subst], rule foldSetD.intros) - apply auto - done - -lemma foldSetD_imp_finite [simp]: "(A, x) : foldSetD D f e ==> finite A" - by (induct set: foldSetD) auto - -lemma finite_imp_foldSetD: - "[| finite A; e : D; !!x y. [| x : A; y : D |] ==> f x y : D |] ==> - EX x. (A, x) : foldSetD D f e" -proof (induct set: Finites) - case empty then show ?case by auto -next - case (insert F x) - then obtain y where y: "(F, y) : foldSetD D f e" by auto - with insert have "y : D" by (auto dest: foldSetD_closed) - with y and insert have "(insert x F, f x y) : foldSetD D f e" - by (intro foldSetD.intros) auto - then show ?case .. -qed - -subsection {* Left-commutative operations *} - -locale LCD = - fixes B :: "'b set" - and D :: "'a set" - and f :: "'b => 'a => 'a" (infixl "\" 70) - assumes left_commute: "[| x : B; y : B; z : D |] ==> x \ (y \ z) = y \ (x \ z)" - and f_closed [simp, intro!]: "!!x y. [| x : B; y : D |] ==> f x y : D" - -lemma (in LCD) foldSetD_closed [dest]: - "(A, z) : foldSetD D f e ==> z : D"; - by (erule foldSetD.elims) auto - -lemma (in LCD) Diff1_foldSetD: - "[| (A - {x}, y) : foldSetD D f e; x : A; A <= B |] ==> - (A, f x y) : foldSetD D f e" - apply (subgoal_tac "x : B") - prefer 2 apply fast - apply (erule insert_Diff [THEN subst], rule foldSetD.intros) - apply auto - done - -lemma (in LCD) foldSetD_imp_finite [simp]: - "(A, x) : foldSetD D f e ==> finite A" - by (induct set: foldSetD) auto - -lemma (in LCD) finite_imp_foldSetD: - "[| finite A; A <= B; e : D |] ==> EX x. (A, x) : foldSetD D f e" -proof (induct set: Finites) - case empty then show ?case by auto -next - case (insert F x) - then obtain y where y: "(F, y) : foldSetD D f e" by auto - with insert have "y : D" by auto - with y and insert have "(insert x F, f x y) : foldSetD D f e" - by (intro foldSetD.intros) auto - then show ?case .. -qed - -lemma (in LCD) foldSetD_determ_aux: - "e : D ==> ALL A x. A <= B & card A < n --> (A, x) : foldSetD D f e --> - (ALL y. (A, y) : foldSetD D f e --> y = x)" - apply (induct n) - apply (auto simp add: less_Suc_eq) - apply (erule foldSetD.cases) - apply blast - apply (erule foldSetD.cases) - apply blast - apply clarify - txt {* force simplification of @{text "card A < card (insert ...)"}. *} - apply (erule rev_mp) - apply (simp add: less_Suc_eq_le) - apply (rule impI) - apply (rename_tac Aa xa ya Ab xb yb, case_tac "xa = xb") - apply (subgoal_tac "Aa = Ab") - prefer 2 apply (blast elim!: equalityE) - apply blast - txt {* case @{prop "xa \ xb"}. *} - apply (subgoal_tac "Aa - {xb} = Ab - {xa} & xb : Aa & xa : Ab") - prefer 2 apply (blast elim!: equalityE) - apply clarify - apply (subgoal_tac "Aa = insert xb Ab - {xa}") - prefer 2 apply blast - apply (subgoal_tac "card Aa <= card Ab") - prefer 2 - apply (rule Suc_le_mono [THEN subst]) - apply (simp add: card_Suc_Diff1) - apply (rule_tac A1 = "Aa - {xb}" in finite_imp_foldSetD [THEN exE]) - apply (blast intro: foldSetD_imp_finite finite_Diff) -(* new subgoal from finite_imp_foldSetD *) - apply best (* blast doesn't seem to solve this *) - apply assumption - apply (frule (1) Diff1_foldSetD) -(* new subgoal from Diff1_foldSetD *) - apply best -(* -apply (best del: foldSetD_closed elim: foldSetD_closed) - apply (rule f_closed) apply assumption apply (rule foldSetD_closed) - prefer 3 apply assumption apply (rule e_closed) - apply (rule f_closed) apply force apply assumption -*) - apply (subgoal_tac "ya = f xb x") - prefer 2 -(* new subgoal to make IH applicable *) - apply (subgoal_tac "Aa <= B") - prefer 2 apply best - apply (blast del: equalityCE) - apply (subgoal_tac "(Ab - {xa}, x) : foldSetD D f e") - prefer 2 apply simp - apply (subgoal_tac "yb = f xa x") - prefer 2 -(* apply (drule_tac x = xa in Diff1_foldSetD) - apply assumption - apply (rule f_closed) apply best apply (rule foldSetD_closed) - prefer 3 apply assumption apply (rule e_closed) - apply (rule f_closed) apply best apply assumption -*) - apply (blast del: equalityCE dest: Diff1_foldSetD) - apply (simp (no_asm_simp)) - apply (rule left_commute) - apply assumption apply best apply best - done - -lemma (in LCD) foldSetD_determ: - "[| (A, x) : foldSetD D f e; (A, y) : foldSetD D f e; e : D; A <= B |] - ==> y = x" - by (blast intro: foldSetD_determ_aux [rule_format]) - -lemma (in LCD) foldD_equality: - "[| (A, y) : foldSetD D f e; e : D; A <= B |] ==> foldD D f e A = y" - by (unfold foldD_def) (blast intro: foldSetD_determ) - -lemma foldD_empty [simp]: - "e : D ==> foldD D f e {} = e" - by (unfold foldD_def) blast - -lemma (in LCD) foldD_insert_aux: - "[| x ~: A; x : B; e : D; A <= B |] ==> - ((insert x A, v) : foldSetD D f e) = - (EX y. (A, y) : foldSetD D f e & v = f x y)" - apply auto - apply (rule_tac A1 = A in finite_imp_foldSetD [THEN exE]) - apply (fastsimp dest: foldSetD_imp_finite) -(* new subgoal by finite_imp_foldSetD *) - apply assumption - apply assumption - apply (blast intro: foldSetD_determ) - done - -lemma (in LCD) foldD_insert: - "[| finite A; x ~: A; x : B; e : D; A <= B |] ==> - foldD D f e (insert x A) = f x (foldD D f e A)" - apply (unfold foldD_def) - apply (simp add: foldD_insert_aux) - apply (rule the_equality) - apply (auto intro: finite_imp_foldSetD - cong add: conj_cong simp add: foldD_def [symmetric] foldD_equality) - done - -lemma (in LCD) foldD_closed [simp]: - "[| finite A; e : D; A <= B |] ==> foldD D f e A : D" -proof (induct set: Finites) - case empty then show ?case by (simp add: foldD_empty) -next - case insert then show ?case by (simp add: foldD_insert) -qed - -lemma (in LCD) foldD_commute: - "[| finite A; x : B; e : D; A <= B |] ==> - f x (foldD D f e A) = foldD D f (f x e) A" - apply (induct set: Finites) - apply simp - apply (auto simp add: left_commute foldD_insert) - done - -lemma Int_mono2: - "[| A <= C; B <= C |] ==> A Int B <= C" - by blast - -lemma (in LCD) foldD_nest_Un_Int: - "[| finite A; finite C; e : D; A <= B; C <= B |] ==> - foldD D f (foldD D f e C) A = foldD D f (foldD D f e (A Int C)) (A Un C)" - apply (induct set: Finites) - apply simp - apply (simp add: foldD_insert foldD_commute Int_insert_left insert_absorb - Int_mono2 Un_subset_iff) - done - -lemma (in LCD) foldD_nest_Un_disjoint: - "[| finite A; finite B; A Int B = {}; e : D; A <= B; C <= B |] - ==> foldD D f e (A Un B) = foldD D f (foldD D f e B) A" - by (simp add: foldD_nest_Un_Int) - --- {* Delete rules to do with @{text foldSetD} relation. *} - -declare foldSetD_imp_finite [simp del] - empty_foldSetDE [rule del] - foldSetD.intros [rule del] -declare (in LCD) - foldSetD_closed [rule del] - -subsection {* Commutative monoids *} - -text {* - We enter a more restrictive context, with @{text "f :: 'a => 'a => 'a"} - instead of @{text "'b => 'a => 'a"}. -*} - -locale ACeD = - fixes D :: "'a set" - and f :: "'a => 'a => 'a" (infixl "\" 70) - and e :: 'a - assumes ident [simp]: "x : D ==> x \ e = x" - and commute: "[| x : D; y : D |] ==> x \ y = y \ x" - and assoc: "[| x : D; y : D; z : D |] ==> (x \ y) \ z = x \ (y \ z)" - and e_closed [simp]: "e : D" - and f_closed [simp]: "[| x : D; y : D |] ==> x \ y : D" - -lemma (in ACeD) left_commute: - "[| x : D; y : D; z : D |] ==> x \ (y \ z) = y \ (x \ z)" -proof - - assume D: "x : D" "y : D" "z : D" - then have "x \ (y \ z) = (y \ z) \ x" by (simp add: commute) - also from D have "... = y \ (z \ x)" by (simp add: assoc) - also from D have "z \ x = x \ z" by (simp add: commute) - finally show ?thesis . -qed - -lemmas (in ACeD) AC = assoc commute left_commute - -lemma (in ACeD) left_ident [simp]: "x : D ==> e \ x = x" -proof - - assume D: "x : D" - have "x \ e = x" by (rule ident) - with D show ?thesis by (simp add: commute) -qed - -lemma (in ACeD) foldD_Un_Int: - "[| finite A; finite B; A <= D; B <= D |] ==> - foldD D f e A \ foldD D f e B = - foldD D f e (A Un B) \ foldD D f e (A Int B)" - apply (induct set: Finites) - apply (simp add: left_commute LCD.foldD_closed [OF LCD.intro [of D]]) -(* left_commute is required to show premise of LCD.intro *) - apply (simp add: AC insert_absorb Int_insert_left - LCD.foldD_insert [OF LCD.intro [of D]] - LCD.foldD_closed [OF LCD.intro [of D]] - Int_mono2 Un_subset_iff) - done - -lemma (in ACeD) foldD_Un_disjoint: - "[| finite A; finite B; A Int B = {}; A <= D; B <= D |] ==> - foldD D f e (A Un B) = foldD D f e A \ foldD D f e B" - by (simp add: foldD_Un_Int - left_commute LCD.foldD_closed [OF LCD.intro [of D]] Un_subset_iff) - -subsection {* Products over Finite Sets *} - -constdefs - finprod :: "[('b, 'm) monoid_scheme, 'a => 'b, 'a set] => 'b" - "finprod G f A == if finite A - then foldD (carrier G) (mult G o f) (one G) A - else arbitrary" - -(* -locale finite_prod = abelian_monoid + var prod + - defines "prod == (%f A. if finite A - then foldD (carrier G) (op \ o f) \ A - else arbitrary)" -*) -(* TODO: nice syntax for the summation operator inside the locale - like \\ i\A. f i, probably needs hand-coded translation *) - -ML_setup {* - -Context.>> (fn thy => (simpset_ref_of thy := - simpset_of thy setsubgoaler asm_full_simp_tac; thy)) *} - -lemma (in abelian_monoid) finprod_empty [simp]: - "finprod G f {} = \" - by (simp add: finprod_def) - -ML_setup {* - -Context.>> (fn thy => (simpset_ref_of thy := - simpset_of thy setsubgoaler asm_simp_tac; thy)) *} - -declare funcsetI [intro] - funcset_mem [dest] - -lemma (in abelian_monoid) finprod_insert [simp]: - "[| finite F; a \ F; f \ F -> carrier G; f a \ carrier G |] ==> - finprod G f (insert a F) = f a \ finprod G f F" - apply (rule trans) - apply (simp add: finprod_def) - apply (rule trans) - apply (rule LCD.foldD_insert [OF LCD.intro [of "insert a F"]]) - apply simp - apply (rule m_lcomm) - apply fast apply fast apply assumption - apply (fastsimp intro: m_closed) - apply simp+ apply fast - apply (auto simp add: finprod_def) - done - -lemma (in abelian_monoid) finprod_one: - "finite A ==> finprod G (%i. \) A = \" -proof (induct set: Finites) - case empty show ?case by simp -next - case (insert A a) - have "(%i. \) \ A -> carrier G" by auto - with insert show ?case by simp -qed - -lemma (in abelian_monoid) finprod_closed [simp]: - fixes A - assumes fin: "finite A" and f: "f \ A -> carrier G" - shows "finprod G f A \ carrier G" -using fin f -proof induct - case empty show ?case by simp -next - case (insert A a) - then have a: "f a \ carrier G" by fast - from insert have A: "f \ A -> carrier G" by fast - from insert A a show ?case by simp -qed - -lemma funcset_Int_left [simp, intro]: - "[| f \ A -> C; f \ B -> C |] ==> f \ A Int B -> C" - by fast - -lemma funcset_Un_left [iff]: - "(f \ A Un B -> C) = (f \ A -> C & f \ B -> C)" - by fast - -lemma (in abelian_monoid) finprod_Un_Int: - "[| finite A; finite B; g \ A -> carrier G; g \ B -> carrier G |] ==> - finprod G g (A Un B) \ finprod G g (A Int B) = - finprod G g A \ finprod G g B" - -- {* The reversed orientation looks more natural, but LOOPS as a simprule! *} -proof (induct set: Finites) - case empty then show ?case by (simp add: finprod_closed) -next - case (insert A a) - then have a: "g a \ carrier G" by fast - from insert have A: "g \ A -> carrier G" by fast - from insert A a show ?case - by (simp add: ac Int_insert_left insert_absorb finprod_closed - Int_mono2 Un_subset_iff) -qed - -lemma (in abelian_monoid) finprod_Un_disjoint: - "[| finite A; finite B; A Int B = {}; - g \ A -> carrier G; g \ B -> carrier G |] - ==> finprod G g (A Un B) = finprod G g A \ finprod G g B" - apply (subst finprod_Un_Int [symmetric]) - apply (auto simp add: finprod_closed) - done - -lemma (in abelian_monoid) finprod_multf: - "[| finite A; f \ A -> carrier G; g \ A -> carrier G |] ==> - finprod G (%x. f x \ g x) A = (finprod G f A \ finprod G g A)" -proof (induct set: Finites) - case empty show ?case by simp -next - case (insert A a) then - have fA: "f : A -> carrier G" by fast - from insert have fa: "f a : carrier G" by fast - from insert have gA: "g : A -> carrier G" by fast - from insert have ga: "g a : carrier G" by fast - from insert have fga: "(%x. f x \ g x) a : carrier G" by (simp add: Pi_def) - from insert have fgA: "(%x. f x \ g x) : A -> carrier G" - by (simp add: Pi_def) - show ?case (* check if all simps are really necessary *) - by (simp add: insert fA fa gA ga fgA fga ac finprod_closed Int_insert_left insert_absorb Int_mono2 Un_subset_iff) -qed - -lemma (in abelian_monoid) finprod_cong': - "[| A = B; g : B -> carrier G; - !!i. i : B ==> f i = g i |] ==> finprod G f A = finprod G g B" -proof - - assume prems: "A = B" "g : B -> carrier G" - "!!i. i : B ==> f i = g i" - show ?thesis - proof (cases "finite B") - case True - then have "!!A. [| A = B; g : B -> carrier G; - !!i. i : B ==> f i = g i |] ==> finprod G f A = finprod G g B" - proof induct - case empty thus ?case by simp - next - case (insert B x) - then have "finprod G f A = finprod G f (insert x B)" by simp - also from insert have "... = f x \ finprod G f B" - proof (intro finprod_insert) - show "finite B" . - next - show "x ~: B" . - next - assume "x ~: B" "!!i. i \ insert x B \ f i = g i" - "g \ insert x B \ carrier G" - thus "f : B -> carrier G" by fastsimp - next - assume "x ~: B" "!!i. i \ insert x B \ f i = g i" - "g \ insert x B \ carrier G" - thus "f x \ carrier G" by fastsimp - qed - also from insert have "... = g x \ finprod G g B" by fastsimp - also from insert have "... = finprod G g (insert x B)" - by (intro finprod_insert [THEN sym]) auto - finally show ?case . - qed - with prems show ?thesis by simp - next - case False with prems show ?thesis by (simp add: finprod_def) - qed -qed - -lemma (in abelian_monoid) finprod_cong: - "[| A = B; !!i. i : B ==> f i = g i; - g : B -> carrier G = True |] ==> finprod G f A = finprod G g B" - by (rule finprod_cong') fast+ - -text {*Usually, if this rule causes a failed congruence proof error, - the reason is that the premise @{text "g : B -> carrier G"} cannot be shown. - Adding @{thm [source] Pi_def} to the simpset is often useful. - For this reason, @{thm [source] abelian_monoid.finprod_cong} - is not added to the simpset by default. -*} - -declare funcsetI [rule del] - funcset_mem [rule del] - -lemma (in abelian_monoid) finprod_0 [simp]: - "f : {0::nat} -> carrier G ==> finprod G f {..0} = f 0" -by (simp add: Pi_def) - -lemma (in abelian_monoid) finprod_Suc [simp]: - "f : {..Suc n} -> carrier G ==> - finprod G f {..Suc n} = (f (Suc n) \ finprod G f {..n})" -by (simp add: Pi_def atMost_Suc) - -lemma (in abelian_monoid) finprod_Suc2: - "f : {..Suc n} -> carrier G ==> - finprod G f {..Suc n} = (finprod G (%i. f (Suc i)) {..n} \ f 0)" -proof (induct n) - case 0 thus ?case by (simp add: Pi_def) -next - case Suc thus ?case by (simp add: m_assoc Pi_def finprod_closed) -qed - -lemma (in abelian_monoid) finprod_mult [simp]: - "[| f : {..n} -> carrier G; g : {..n} -> carrier G |] ==> - finprod G (%i. f i \ g i) {..n::nat} = - finprod G f {..n} \ finprod G g {..n}" - by (induct n) (simp_all add: ac Pi_def finprod_closed) - -end - diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/poly/PolyHomo.thy --- a/src/HOL/Algebra/poly/PolyHomo.thy Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/poly/PolyHomo.thy Wed Apr 30 10:01:35 2003 +0200 @@ -4,7 +4,7 @@ Author: Clemens Ballarin, started 15 April 1997 *) -PolyHomo = UnivPoly + +PolyHomo = UnivPoly2 + consts EVAL2 :: "['a::ring => 'b, 'b, 'a up] => 'b::ring" diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/poly/UnivPoly.ML --- a/src/HOL/Algebra/poly/UnivPoly.ML Tue Apr 29 12:36:49 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,359 +0,0 @@ -(* - Degree of polynomials - $Id$ - written by Clemens Ballarin, started 22 January 1997 -*) - -(* -(* Relating degree and bound *) - -Goal "[| bound m f; f n ~= 0 |] ==> n <= m"; -by (force_tac (claset() addDs [inst "m" "n" boundD], - simpset()) 1); -qed "below_bound"; - -goal UnivPoly.thy "bound (LEAST n. bound n (Rep_UP p)) (Rep_UP p)"; -by (rtac exE 1); -by (rtac LeastI 2); -by (assume_tac 2); -by (res_inst_tac [("a", "Rep_UP p")] CollectD 1); -by (rtac (rewrite_rule [UP_def] Rep_UP) 1); -qed "Least_is_bound"; - -Goalw [coeff_def, deg_def] - "!! p. ALL m. n < m --> coeff m p = 0 ==> deg p <= n"; -by (rtac Least_le 1); -by (Fast_tac 1); -qed "deg_aboveI"; - -Goalw [coeff_def, deg_def] - "(n ~= 0 --> coeff n p ~= 0) ==> n <= deg p"; -by (case_tac "n = 0" 1); -(* Case n=0 *) -by (Asm_simp_tac 1); -(* Case n~=0 *) -by (rotate_tac 1 1); -by (Asm_full_simp_tac 1); -by (rtac below_bound 1); -by (assume_tac 2); -by (rtac Least_is_bound 1); -qed "deg_belowI"; - -Goalw [coeff_def, deg_def] - "deg p < m ==> coeff m p = 0"; -by (rtac exE 1); (* create !! x. *) -by (rtac boundD 2); -by (assume_tac 3); -by (rtac LeastI 2); -by (assume_tac 2); -by (res_inst_tac [("a", "Rep_UP p")] CollectD 1); -by (rtac (rewrite_rule [UP_def] Rep_UP) 1); -qed "deg_aboveD"; - -Goalw [deg_def] - "deg p = Suc y ==> ~ bound y (Rep_UP p)"; -by (rtac not_less_Least 1); -by (Asm_simp_tac 1); -val lemma1 = result(); - -Goalw [deg_def, coeff_def] - "deg p = Suc y ==> coeff (deg p) p ~= 0"; -by (rtac ccontr 1); -by (dtac notnotD 1); -by (cut_inst_tac [("p", "p")] Least_is_bound 1); -by (subgoal_tac "bound y (Rep_UP p)" 1); -(* prove subgoal *) -by (rtac boundI 2); -by (case_tac "Suc y < m" 2); -(* first case *) -by (rtac boundD 2); -by (assume_tac 2); -by (Asm_simp_tac 2); -(* second case *) -by (dtac leI 2); -by (dtac Suc_leI 2); -by (dtac le_anti_sym 2); -by (assume_tac 2); -by (Asm_full_simp_tac 2); -(* end prove subgoal *) -by (fold_goals_tac [deg_def]); -by (dtac lemma1 1); -by (etac notE 1); -by (assume_tac 1); -val lemma2 = result(); - -Goal "deg p ~= 0 ==> coeff (deg p) p ~= 0"; -by (rtac lemma2 1); -by (Full_simp_tac 1); -by (dtac Suc_pred 1); -by (rtac sym 1); -by (Asm_simp_tac 1); -qed "deg_lcoeff"; - -Goal "p ~= 0 ==> coeff (deg p) p ~= 0"; -by (etac contrapos_np 1); -by (case_tac "deg p = 0" 1); -by (blast_tac (claset() addSDs [deg_lcoeff]) 2); -by (rtac up_eqI 1); -by (case_tac "n=0" 1); -by (rotate_tac ~2 1); -by (Asm_full_simp_tac 1); -by (asm_full_simp_tac (simpset() addsimps [deg_aboveD]) 1); -qed "nonzero_lcoeff"; - -Goal "(deg p <= n) = bound n (Rep_UP p)"; -by (rtac iffI 1); -(* ==> *) -by (rtac boundI 1); -by (fold_goals_tac [coeff_def]); -by (rtac deg_aboveD 1); -by (fast_arith_tac 1); -(* <== *) -by (rtac deg_aboveI 1); -by (rewtac coeff_def); -by (Fast_tac 1); -qed "deg_above_is_bound"; - -(* Lemmas on the degree function *) - -Goalw [max_def] - "!! p::'a::ring up. deg (p + q) <= max (deg p) (deg q)"; -by (case_tac "deg p <= deg q" 1); -(* case deg p <= deg q *) -by (rtac deg_aboveI 1); -by (Asm_simp_tac 1); -by (strip_tac 1); -by (dtac le_less_trans 1); -by (assume_tac 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); -(* case deg p > deg q *) -by (rtac deg_aboveI 1); -by (Asm_simp_tac 1); -by (dtac not_leE 1); -by (strip_tac 1); -by (dtac less_trans 1); -by (assume_tac 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); -qed "deg_add"; - -Goal "!!p::('a::ring up). deg p < deg q ==> deg (p + q) = deg q"; -by (rtac order_antisym 1); -by (rtac le_trans 1); -by (rtac deg_add 1); -by (Asm_simp_tac 1); -by (rtac deg_belowI 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD, deg_lcoeff]) 1); -qed "deg_add_equal"; - -Goal "deg (monom m::'a::ring up) <= m"; -by (asm_simp_tac - (simpset() addsimps [deg_aboveI, less_not_refl2 RS not_sym]) 1); -qed "deg_monom_ring"; - -Goal "deg (monom m::'a::domain up) = m"; -by (rtac le_anti_sym 1); -(* <= *) -by (rtac deg_monom_ring 1); -(* >= *) -by (asm_simp_tac - (simpset() addsimps [deg_belowI, less_not_refl2 RS not_sym]) 1); -qed "deg_monom"; - -Goal "!! a::'a::ring. deg (const a) = 0"; -by (rtac le_anti_sym 1); -by (rtac deg_aboveI 1); -by (simp_tac (simpset() addsimps [less_not_refl2]) 1); -by (rtac deg_belowI 1); -by (simp_tac (simpset() addsimps [less_not_refl2]) 1); -qed "deg_const"; - -Goal "deg (0::'a::ringS up) = 0"; -by (rtac le_anti_sym 1); -by (rtac deg_aboveI 1); -by (Simp_tac 1); -by (rtac deg_belowI 1); -by (Simp_tac 1); -qed "deg_zero"; - -Goal "deg (<1>::'a::ring up) = 0"; -by (rtac le_anti_sym 1); -by (rtac deg_aboveI 1); -by (simp_tac (simpset() addsimps [less_not_refl2]) 1); -by (rtac deg_belowI 1); -by (Simp_tac 1); -qed "deg_one"; - -Goal "!!p::('a::ring) up. deg (-p) = deg p"; -by (rtac le_anti_sym 1); -(* <= *) -by (simp_tac (simpset() addsimps [deg_aboveI, deg_aboveD]) 1); -by (simp_tac (simpset() addsimps [deg_belowI, deg_lcoeff, uminus_monom_neq]) 1); -qed "deg_uminus"; - -Addsimps [deg_monom, deg_const, deg_zero, deg_one, deg_uminus]; - -Goal - "!! a::'a::ring. deg (a *s p) <= (if a = 0 then 0 else deg p)"; -by (case_tac "a = 0" 1); -by (REPEAT (asm_simp_tac (simpset() addsimps [deg_aboveI, deg_aboveD]) 1)); -qed "deg_smult_ring"; - -Goal - "!! a::'a::domain. deg (a *s p) = (if a = 0 then 0 else deg p)"; -by (rtac le_anti_sym 1); -by (rtac deg_smult_ring 1); -by (case_tac "a = 0" 1); -by (REPEAT (asm_simp_tac (simpset() addsimps [deg_belowI, deg_lcoeff]) 1)); -qed "deg_smult"; - -Goal - "!! p::'a::ring up. [| deg p + deg q < k |] ==> \ -\ coeff i p * coeff (k - i) q = 0"; -by (simp_tac (simpset() addsimps [coeff_def]) 1); -by (rtac bound_mult_zero 1); -by (assume_tac 3); -by (simp_tac (simpset() addsimps [deg_above_is_bound RS sym]) 1); -by (simp_tac (simpset() addsimps [deg_above_is_bound RS sym]) 1); -qed "deg_above_mult_zero"; - -Goal - "!! p::'a::ring up. deg (p * q) <= deg p + deg q"; -by (rtac deg_aboveI 1); -by (asm_simp_tac (simpset() addsimps [deg_above_mult_zero]) 1); -qed "deg_mult_ring"; - -goal Main.thy - "!!k::nat. k < n ==> m < n + m - k"; -by (arith_tac 1); -qed "less_add_diff"; - -Goal "!!p. coeff n p ~= 0 ==> n <= deg p"; -(* More general than deg_belowI, and simplifies the next proof! *) -by (rtac deg_belowI 1); -by (Fast_tac 1); -qed "deg_below2I"; - -Goal - "!! p::'a::domain up. \ -\ [| p ~= 0; q ~= 0 |] ==> deg (p * q) = deg p + deg q"; -by (rtac le_anti_sym 1); -by (rtac deg_mult_ring 1); -(* deg p + deg q <= deg (p * q) *) -by (rtac deg_below2I 1); -by (Simp_tac 1); -(* -by (rtac conjI 1); -by (rtac impI 1); -*) -by (res_inst_tac [("m", "deg p"), ("n", "deg p + deg q")] SUM_extend 1); -by (rtac le_add1 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); -by (res_inst_tac [("m", "deg p"), ("n", "deg p")] SUM_extend_below 1); -by (rtac le_refl 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); -by (asm_simp_tac (simpset() addsimps [nonzero_lcoeff]) 1); -(* -by (rtac impI 1); -by (res_inst_tac [("m", "deg p"), ("n", "deg p + deg q")] SUM_extend 1); -by (rtac le_add1 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); -by (res_inst_tac [("m", "deg p"), ("n", "deg p")] SUM_extend_below 1); -by (rtac le_refl 1); -by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); -by (asm_simp_tac (simpset() addsimps [nonzero_lcoeff]) 1); -*) -qed "deg_mult"; - -Addsimps [deg_smult, deg_mult]; - -(* Representation theorems about polynomials *) - -goal PolyRing.thy - "!! p::nat=>'a::ring up. \ -\ coeff k (setsum p {..n}) = setsum (%i. coeff k (p i)) {..n}"; -by (induct_tac "n" 1); -by Auto_tac; -qed "coeff_SUM"; - -goal UnivPoly.thy - "!! f::(nat=>'a::ring). \ -\ bound n f ==> setsum (%i. if i = x then f i else 0) {..n} = f x"; -by (simp_tac (simpset() addsimps [SUM_if_singleton]) 1); -by (auto_tac - (claset() addDs [not_leE], - simpset())); -qed "bound_SUM_if"; - -Goal - "!! p::'a::ring up. deg p <= n ==> \ -\ setsum (%i. coeff i p *s monom i) {..n} = p"; -by (rtac up_eqI 1); -by (simp_tac (simpset() addsimps [coeff_SUM]) 1); -by (rtac trans 1); -by (res_inst_tac [("x", "na")] bound_SUM_if 2); -by (full_simp_tac (simpset() addsimps [deg_above_is_bound, coeff_def]) 2); -by (rtac SUM_cong 1); -by (rtac refl 1); -by (Asm_simp_tac 1); -qed "up_repr"; - -Goal - "!! p::'a::ring up. [| deg p <= n; P p |] ==> \ -\ P (setsum (%i. coeff i p *s monom i) {..n})"; -by (asm_simp_tac (simpset() addsimps [up_repr]) 1); -qed "up_reprD"; - -Goal - "!! p::'a::ring up. \ -\ [| deg p <= n; P (setsum (%i. coeff i p *s monom i) {..n}) |] \ -\ ==> P p"; -by (asm_full_simp_tac (simpset() addsimps [up_repr]) 1); -qed "up_repr2D"; - -(* -Goal - "!! p::'a::ring up. [| deg p <= n; deg q <= m |] ==> \ -\ (SUM n (%i. coeff i p *s monom i) = SUM m (%i. coeff i q *s monom i)) \ -\ = (coeff k f = coeff k g) -... -qed "up_unique"; -*) - -(* Polynomials over integral domains are again integral domains *) - -Goal "!!p::'a::domain up. p * q = 0 ==> p = 0 | q = 0"; -by (rtac classical 1); -by (subgoal_tac "deg p = 0 & deg q = 0" 1); -by (res_inst_tac [("p", "p"), ("n", "0")] up_repr2D 1); -by (Asm_simp_tac 1); -by (res_inst_tac [("p", "q"), ("n", "0")] up_repr2D 1); -by (Asm_simp_tac 1); -by (subgoal_tac "coeff 0 p = 0 | coeff 0 q = 0" 1); -by (force_tac (claset() addIs [up_eqI], simpset()) 1); -by (rtac integral 1); -by (subgoal_tac "coeff 0 (p * q) = 0" 1); -by (Asm_simp_tac 2); -by (Full_simp_tac 1); -by (dres_inst_tac [("f", "deg")] arg_cong 1); -by (Asm_full_simp_tac 1); -qed "up_integral"; - -Goal "!! a::'a::domain. a *s p = 0 ==> a = 0 | p = 0"; -by (full_simp_tac (simpset() addsimps [const_mult_is_smult RS sym]) 1); -by (dtac up_integral 1); -by Auto_tac; -by (rtac (const_inj RS injD) 1); -by (Simp_tac 1); -qed "smult_integral"; -*) - -(* Divisibility and degree *) - -Goalw [dvd_def] - "!! p::'a::domain up. [| p dvd q; q ~= 0 |] ==> deg p <= deg q"; -by (etac exE 1); -by (hyp_subst_tac 1); -by (case_tac "p = 0" 1); -by (case_tac "k = 0" 2); -by Auto_tac; -qed "dvd_imp_deg"; diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/poly/UnivPoly.thy --- a/src/HOL/Algebra/poly/UnivPoly.thy Tue Apr 29 12:36:49 2003 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,779 +0,0 @@ -(* - Title: Univariate Polynomials - Id: $Id$ - Author: Clemens Ballarin, started 9 December 1996 - Copyright: Clemens Ballarin -*) - -header {* Univariate Polynomials *} - -theory UnivPoly = Abstract: - -(* already proved in Finite_Set.thy - -lemma setsum_cong: - "[| A = B; !!i. i : B ==> f i = g i |] ==> setsum f A = setsum g B" -proof - - assume prems: "A = B" "!!i. i : B ==> f i = g i" - show ?thesis - proof (cases "finite B") - case True - then have "!!A. [| A = B; !!i. i : B ==> f i = g i |] ==> - setsum f A = setsum g B" - proof induct - case empty thus ?case by simp - next - case insert thus ?case by simp - qed - with prems show ?thesis by simp - next - case False with prems show ?thesis by (simp add: setsum_def) - qed -qed -*) - -(* Instruct simplifier to simplify assumptions introduced by congs. - This makes setsum_cong more convenient to use, because assumptions - like i:{m..n} get simplified (to m <= i & i <= n). *) - -ML_setup {* - -Addcongs [thm "setsum_cong"]; -Context.>> (fn thy => (simpset_ref_of thy := - simpset_of thy setsubgoaler asm_full_simp_tac; thy)) *} - -section {* Definition of type up *} - -constdefs - bound :: "[nat, nat => 'a::zero] => bool" - "bound n f == (ALL i. n < i --> f i = 0)" - -lemma boundI [intro!]: "[| !! m. n < m ==> f m = 0 |] ==> bound n f" -proof (unfold bound_def) -qed fast - -lemma boundE [elim?]: "[| bound n f; (!! m. n < m ==> f m = 0) ==> P |] ==> P" -proof (unfold bound_def) -qed fast - -lemma boundD [dest]: "[| bound n f; n < m |] ==> f m = 0" -proof (unfold bound_def) -qed fast - -lemma bound_below: - assumes bound: "bound m f" and nonzero: "f n ~= 0" shows "n <= m" -proof (rule classical) - assume "~ ?thesis" - then have "m < n" by arith - with bound have "f n = 0" .. - with nonzero show ?thesis by contradiction -qed - -typedef (UP) - ('a) up = "{f :: nat => 'a::zero. EX n. bound n f}" -by (rule+) (* Question: what does trace_rule show??? *) - -section {* Constants *} - -consts - coeff :: "['a up, nat] => ('a::zero)" - monom :: "['a::zero, nat] => 'a up" ("(3_*X^/_)" [71, 71] 70) - "*s" :: "['a::{zero, times}, 'a up] => 'a up" (infixl 70) - -defs - coeff_def: "coeff p n == Rep_UP p n" - monom_def: "monom a n == Abs_UP (%i. if i=n then a else 0)" - smult_def: "a *s p == Abs_UP (%i. a * Rep_UP p i)" - -lemma coeff_bound_ex: "EX n. bound n (coeff p)" -proof - - have "(%n. coeff p n) : UP" by (simp add: coeff_def Rep_UP) - then obtain n where "bound n (coeff p)" by (unfold UP_def) fast - then show ?thesis .. -qed - -lemma bound_coeff_obtain: - assumes prem: "(!!n. bound n (coeff p) ==> P)" shows "P" -proof - - have "(%n. coeff p n) : UP" by (simp add: coeff_def Rep_UP) - then obtain n where "bound n (coeff p)" by (unfold UP_def) fast - with prem show P . -qed - -text {* Ring operations *} - -instance up :: (zero) zero .. -instance up :: (one) one .. -instance up :: (plus) plus .. -instance up :: (minus) minus .. -instance up :: (times) times .. -instance up :: (inverse) inverse .. -instance up :: (power) power .. - -defs - up_add_def: "p + q == Abs_UP (%n. Rep_UP p n + Rep_UP q n)" - up_mult_def: "p * q == Abs_UP (%n::nat. setsum - (%i. Rep_UP p i * Rep_UP q (n-i)) {..n})" - up_zero_def: "0 == monom 0 0" - up_one_def: "1 == monom 1 0" - up_uminus_def:"- p == (- 1) *s p" - (* easier to use than "Abs_UP (%i. - Rep_UP p i)" *) - (* note: - 1 is different from -1; latter is of class number *) - - up_minus_def: "(a::'a::{plus, minus} up) - b == a + (-b)" - up_inverse_def: "inverse (a::'a::{zero, one, times, inverse} up) == - (if a dvd 1 then THE x. a*x = 1 else 0)" - up_divide_def: "(a::'a::{times, inverse} up) / b == a * inverse b" - up_power_def: "(a::'a::{one, times, power} up) ^ n == - nat_rec 1 (%u b. b * a) n" - -subsection {* Effect of operations on coefficients *} - -lemma coeff_monom [simp]: "coeff (monom a m) n = (if m=n then a else 0)" -proof - - have "(%n. if n = m then a else 0) : UP" - using UP_def by force - from this show ?thesis - by (simp add: coeff_def monom_def Abs_UP_inverse Rep_UP) -qed - -lemma coeff_zero [simp]: "coeff 0 n = 0" -proof (unfold up_zero_def) -qed simp - -lemma coeff_one [simp]: "coeff 1 n = (if n=0 then 1 else 0)" -proof (unfold up_one_def) -qed simp - -(* term order -lemma coeff_smult [simp]: "coeff (a *s p) n = (a::'a::ring) * coeff p n" -proof - - have "!!f. f : UP ==> (%n. a * f n) : UP" - by (unfold UP_def) (force simp add: ring_simps) -*) (* this force step is slow *) -(* then show ?thesis - apply (simp add: coeff_def smult_def Abs_UP_inverse Rep_UP) -qed -*) -lemma coeff_smult [simp]: "coeff (a *s p) n = (a::'a::ring) * coeff p n" -proof - - have "Rep_UP p : UP ==> (%n. a * Rep_UP p n) : UP" - by (unfold UP_def) (force simp add: ring_simps) - (* this force step is slow *) - then show ?thesis - by (simp add: coeff_def smult_def Abs_UP_inverse Rep_UP) -qed - -lemma coeff_add [simp]: "coeff (p+q) n = (coeff p n + coeff q n::'a::ring)" -proof - - { - fix f g - assume fup: "(f::nat=>'a::ring) : UP" and gup: "(g::nat=>'a::ring) : UP" - have "(%i. f i + g i) : UP" - proof - - from fup obtain n where boundn: "bound n f" - by (unfold UP_def) fast - from gup obtain m where boundm: "bound m g" - by (unfold UP_def) fast - have "bound (max n m) (%i. (f i + g i))" - proof - fix i - assume "max n m < i" - with boundn and boundm show "f i + g i = 0" - by (fastsimp simp add: ring_simps) - qed - then show "(%i. (f i + g i)) : UP" - by (unfold UP_def) fast - qed - } - then show ?thesis - by (simp add: coeff_def up_add_def Abs_UP_inverse Rep_UP) -qed - -lemma coeff_mult [simp]: - "coeff (p * q) n = (setsum (%i. coeff p i * coeff q (n-i)) {..n}::'a::ring)" -proof - - { - fix f g - assume fup: "(f::nat=>'a::ring) : UP" and gup: "(g::nat=>'a::ring) : UP" - have "(%n. setsum (%i. f i * g (n-i)) {..n}) : UP" - proof - - from fup obtain n where "bound n f" - by (unfold UP_def) fast - from gup obtain m where "bound m g" - by (unfold UP_def) fast - have "bound (n + m) (%n. setsum (%i. f i * g (n-i)) {..n})" - proof - fix k - assume bound: "n + m < k" - { - fix i - have "f i * g (k-i) = 0" - proof cases - assume "n < i" - show ?thesis by (auto! simp add: ring_simps) - next - assume "~ (n < i)" - with bound have "m < k-i" by arith - then show ?thesis by (auto! simp add: ring_simps) - qed - } - then show "setsum (%i. f i * g (k-i)) {..k} = 0" - by (simp add: ring_simps) - qed - then show "(%n. setsum (%i. f i * g (n-i)) {..n}) : UP" - by (unfold UP_def) fast - qed - } - then show ?thesis - by (simp add: coeff_def up_mult_def Abs_UP_inverse Rep_UP) -qed - -lemma coeff_uminus [simp]: "coeff (-p) n = (-coeff p n::'a::ring)" -by (unfold up_uminus_def) (simp add: ring_simps) - -(* Other lemmas *) - -lemma up_eqI: assumes prem: "(!! n. coeff p n = coeff q n)" shows "p = q" -proof - - have "p = Abs_UP (%u. Rep_UP p u)" by (simp add: Rep_UP_inverse) - also from prem have "... = Abs_UP (Rep_UP q)" by (simp only: coeff_def) - also have "... = q" by (simp add: Rep_UP_inverse) - finally show ?thesis . -qed - -(* ML_setup {* Addsimprocs [ring_simproc] *} *) - -instance up :: (ring) ring -proof - fix p q r :: "'a::ring up" - fix n - show "(p + q) + r = p + (q + r)" - by (rule up_eqI) simp - show "0 + p = p" - by (rule up_eqI) simp - show "(-p) + p = 0" - by (rule up_eqI) simp - show "p + q = q + p" - by (rule up_eqI) simp - show "(p * q) * r = p * (q * r)" - proof (rule up_eqI) - fix n - { - fix k and a b c :: "nat=>'a::ring" - have "k <= n ==> - setsum (%j. setsum (%i. a i * b (j-i)) {..j} * c (n-j)) {..k} = - setsum (%j. a j * setsum (%i. b i * c (n-j-i)) {..k-j}) {..k}" - (is "_ ==> ?eq k") - proof (induct k) - case 0 show ?case by simp - next - case (Suc k) - then have "k <= n" by arith - then have "?eq k" by (rule Suc) - then show ?case - by (simp add: Suc_diff_le natsum_ldistr) - qed - } - then show "coeff ((p * q) * r) n = coeff (p * (q * r)) n" - by simp - qed - show "1 * p = p" - proof (rule up_eqI) - fix n - show "coeff (1 * p) n = coeff p n" - proof (cases n) - case 0 then show ?thesis by simp - next - case Suc then show ?thesis by (simp del: natsum_Suc add: natsum_Suc2) - qed - qed - show "(p + q) * r = p * r + q * r" - by (rule up_eqI) simp - show "p * q = q * p" - proof (rule up_eqI) - fix n - { - fix k - fix a b :: "nat=>'a::ring" - have "k <= n ==> - setsum (%i. a i * b (n-i)) {..k} = - setsum (%i. a (k-i) * b (i+n-k)) {..k}" - (is "_ ==> ?eq k") - proof (induct k) - case 0 show ?case by simp - next - case (Suc k) then show ?case by (subst natsum_Suc2) simp - qed - } - then show "coeff (p * q) n = coeff (q * p) n" - by simp - qed - - show "p - q = p + (-q)" - by (simp add: up_minus_def) - show "inverse p = (if p dvd 1 then THE x. p*x = 1 else 0)" - by (simp add: up_inverse_def) - show "p / q = p * inverse q" - by (simp add: up_divide_def) - show "p ^ n = nat_rec 1 (%u b. b * p) n" - by (simp add: up_power_def) - qed - -(* Further properties of monom *) - -lemma monom_zero [simp]: - "monom 0 n = 0" - by (simp add: monom_def up_zero_def) -(* term order: application of coeff_mult goes wrong: rule not symmetric -lemma monom_mult_is_smult: - "monom (a::'a::ring) 0 * p = a *s p" -proof (rule up_eqI) - fix k - show "coeff (monom a 0 * p) k = coeff (a *s p) k" - proof (cases k) - case 0 then show ?thesis by simp - next - case Suc then show ?thesis by simp - qed -qed -*) -ML_setup {* Delsimprocs [ring_simproc] *} - -lemma monom_mult_is_smult: - "monom (a::'a::ring) 0 * p = a *s p" -proof (rule up_eqI) - fix k - have "coeff (p * monom a 0) k = coeff (a *s p) k" - proof (cases k) - case 0 then show ?thesis by simp ring - next - case Suc then show ?thesis by (simp add: ring_simps) ring - qed - then show "coeff (monom a 0 * p) k = coeff (a *s p) k" by ring -qed - -ML_setup {* Addsimprocs [ring_simproc] *} - -lemma monom_add [simp]: - "monom (a + b) n = monom (a::'a::ring) n + monom b n" -by (rule up_eqI) simp - -lemma monom_mult_smult: - "monom (a * b) n = a *s monom (b::'a::ring) n" -by (rule up_eqI) simp - -lemma monom_uminus [simp]: - "monom (-a) n = - monom (a::'a::ring) n" -by (rule up_eqI) simp - -lemma monom_one [simp]: - "monom 1 0 = 1" -by (simp add: up_one_def) - -lemma monom_inj: - "(monom a n = monom b n) = (a = b)" -proof - assume "monom a n = monom b n" - then have "coeff (monom a n) n = coeff (monom b n) n" by simp - then show "a = b" by simp -next - assume "a = b" then show "monom a n = monom b n" by simp -qed - -(* Properties of *s: - Polynomials form a module *) - -lemma smult_l_distr: - "(a + b::'a::ring) *s p = a *s p + b *s p" -by (rule up_eqI) simp - -lemma smult_r_distr: - "(a::'a::ring) *s (p + q) = a *s p + a *s q" -by (rule up_eqI) simp - -lemma smult_assoc1: - "(a * b::'a::ring) *s p = a *s (b *s p)" -by (rule up_eqI) simp - -lemma smult_one [simp]: - "(1::'a::ring) *s p = p" -by (rule up_eqI) simp - -(* Polynomials form an algebra *) - -ML_setup {* Delsimprocs [ring_simproc] *} - -lemma smult_assoc2: - "(a *s p) * q = (a::'a::ring) *s (p * q)" -by (rule up_eqI) (simp add: natsum_rdistr m_assoc) -(* Simproc fails. *) - -ML_setup {* Addsimprocs [ring_simproc] *} - -(* the following can be derived from the above ones, - for generality reasons, it is therefore done *) - -lemma smult_l_null [simp]: - "(0::'a::ring) *s p = 0" -proof - - fix a - have "0 *s p = (0 *s p + a *s p) + - (a *s p)" by simp - also have "... = (0 + a) *s p + - (a *s p)" by (simp only: smult_l_distr) - also have "... = 0" by simp - finally show ?thesis . -qed - -lemma smult_r_null [simp]: - "(a::'a::ring) *s 0 = 0"; -proof - - fix p - have "a *s 0 = (a *s 0 + a *s p) + - (a *s p)" by simp - also have "... = a *s (0 + p) + - (a *s p)" by (simp only: smult_r_distr) - also have "... = 0" by simp - finally show ?thesis . -qed - -lemma smult_l_minus: - "(-a::'a::ring) *s p = - (a *s p)" -proof - - have "(-a) *s p = (-a *s p + a *s p) + -(a *s p)" by simp - also have "... = (-a + a) *s p + -(a *s p)" by (simp only: smult_l_distr) - also have "... = -(a *s p)" by simp - finally show ?thesis . -qed - -lemma smult_r_minus: - "(a::'a::ring) *s (-p) = - (a *s p)" -proof - - have "a *s (-p) = (a *s -p + a *s p) + -(a *s p)" by simp - also have "... = a *s (-p + p) + -(a *s p)" by (simp only: smult_r_distr) - also have "... = -(a *s p)" by simp - finally show ?thesis . -qed - -section {* The degree function *} - -constdefs - deg :: "('a::zero) up => nat" - "deg p == LEAST n. bound n (coeff p)" - -lemma deg_aboveI: - "(!!m. n < m ==> coeff p m = 0) ==> deg p <= n" -by (unfold deg_def) (fast intro: Least_le) - -lemma deg_aboveD: - assumes prem: "deg p < m" shows "coeff p m = 0" -proof - - obtain n where "bound n (coeff p)" by (rule bound_coeff_obtain) - then have "bound (deg p) (coeff p)" by (unfold deg_def, rule LeastI) - then show "coeff p m = 0" by (rule boundD) -qed - -lemma deg_belowI: - assumes prem: "n ~= 0 ==> coeff p n ~= 0" shows "n <= deg p" -(* logically, this is a slightly stronger version of deg_aboveD *) -proof (cases "n=0") - case True then show ?thesis by simp -next - case False then have "coeff p n ~= 0" by (rule prem) - then have "~ deg p < n" by (fast dest: deg_aboveD) - then show ?thesis by arith -qed - -lemma lcoeff_nonzero_deg: - assumes deg: "deg p ~= 0" shows "coeff p (deg p) ~= 0" -proof - - obtain m where "deg p <= m" and m_coeff: "coeff p m ~= 0" - proof - - have minus: "!!(n::nat) m. n ~= 0 ==> (n - Suc 0 < m) = (n <= m)" - by arith (* make public?, why does proof not work with "1" *) - from deg have "deg p - 1 < (LEAST n. bound n (coeff p))" - by (unfold deg_def) arith - then have "~ bound (deg p - 1) (coeff p)" by (rule not_less_Least) - then have "EX m. deg p - 1 < m & coeff p m ~= 0" - by (unfold bound_def) fast - then have "EX m. deg p <= m & coeff p m ~= 0" by (simp add: deg minus) - then show ?thesis by auto - qed - with deg_belowI have "deg p = m" by fastsimp - with m_coeff show ?thesis by simp -qed - -lemma lcoeff_nonzero_nonzero: - assumes deg: "deg p = 0" and nonzero: "p ~= 0" shows "coeff p 0 ~= 0" -proof - - have "EX m. coeff p m ~= 0" - proof (rule classical) - assume "~ ?thesis" - then have "p = 0" by (auto intro: up_eqI) - with nonzero show ?thesis by contradiction - qed - then obtain m where coeff: "coeff p m ~= 0" .. - then have "m <= deg p" by (rule deg_belowI) - then have "m = 0" by (simp add: deg) - with coeff show ?thesis by simp -qed - -lemma lcoeff_nonzero: - "p ~= 0 ==> coeff p (deg p) ~= 0" -proof (cases "deg p = 0") - case True - assume "p ~= 0" - with True show ?thesis by (simp add: lcoeff_nonzero_nonzero) -next - case False - assume "p ~= 0" - with False show ?thesis by (simp add: lcoeff_nonzero_deg) -qed - -lemma deg_eqI: - "[| !!m. n < m ==> coeff p m = 0; - !!n. n ~= 0 ==> coeff p n ~= 0|] ==> deg p = n" -by (fast intro: le_anti_sym deg_aboveI deg_belowI) - -(* Degree and polynomial operations *) - -lemma deg_add [simp]: - "deg ((p::'a::ring up) + q) <= max (deg p) (deg q)" -proof (cases "deg p <= deg q") - case True show ?thesis by (rule deg_aboveI) (simp add: True deg_aboveD) -next - case False show ?thesis by (rule deg_aboveI) (simp add: False deg_aboveD) -qed - -lemma deg_monom_ring: - "deg (monom a n::'a::ring up) <= n" -by (rule deg_aboveI) simp - -lemma deg_monom [simp]: - "a ~= 0 ==> deg (monom a n::'a::ring up) = n" -by (fastsimp intro: le_anti_sym deg_aboveI deg_belowI) - -lemma deg_const [simp]: - "deg (monom (a::'a::ring) 0) = 0" -proof (rule le_anti_sym) - show "deg (monom a 0) <= 0" by (rule deg_aboveI) simp -next - show "0 <= deg (monom a 0)" by (rule deg_belowI) simp -qed - -lemma deg_zero [simp]: - "deg 0 = 0" -proof (rule le_anti_sym) - show "deg 0 <= 0" by (rule deg_aboveI) simp -next - show "0 <= deg 0" by (rule deg_belowI) simp -qed - -lemma deg_one [simp]: - "deg 1 = 0" -proof (rule le_anti_sym) - show "deg 1 <= 0" by (rule deg_aboveI) simp -next - show "0 <= deg 1" by (rule deg_belowI) simp -qed - -lemma uminus_monom: - "!!a::'a::ring. (-a = 0) = (a = 0)" -proof - fix a::"'a::ring" - assume "a = 0" - then show "-a = 0" by simp -next - fix a::"'a::ring" - assume "- a = 0" - then have "-(- a) = 0" by simp - then show "a = 0" by simp -qed - -lemma deg_uminus [simp]: - "deg (-p::('a::ring) up) = deg p" -proof (rule le_anti_sym) - show "deg (- p) <= deg p" by (simp add: deg_aboveI deg_aboveD) -next - show "deg p <= deg (- p)" - by (simp add: deg_belowI lcoeff_nonzero_deg uminus_monom) -qed - -lemma deg_smult_ring: - "deg ((a::'a::ring) *s p) <= (if a = 0 then 0 else deg p)" -proof (cases "a = 0") -qed (simp add: deg_aboveI deg_aboveD)+ - -lemma deg_smult [simp]: - "deg ((a::'a::domain) *s p) = (if a = 0 then 0 else deg p)" -proof (rule le_anti_sym) - show "deg (a *s p) <= (if a = 0 then 0 else deg p)" by (rule deg_smult_ring) -next - show "(if a = 0 then 0 else deg p) <= deg (a *s p)" - proof (cases "a = 0") - qed (simp, simp add: deg_belowI lcoeff_nonzero_deg integral_iff) -qed - -lemma deg_mult_ring: - "deg (p * q::'a::ring up) <= deg p + deg q" -proof (rule deg_aboveI) - fix m - assume boundm: "deg p + deg q < m" - { - fix k i - assume boundk: "deg p + deg q < k" - then have "coeff p i * coeff q (k - i) = 0" - proof (cases "deg p < i") - case True then show ?thesis by (simp add: deg_aboveD) - next - case False with boundk have "deg q < k - i" by arith - then show ?thesis by (simp add: deg_aboveD) - qed - } - (* This is similar to bound_mult_zero and deg_above_mult_zero in the old - proofs. *) - with boundm show "coeff (p * q) m = 0" by simp -qed - -lemma deg_mult [simp]: - "[| (p::'a::domain up) ~= 0; q ~= 0|] ==> deg (p * q) = deg p + deg q" -proof (rule le_anti_sym) - show "deg (p * q) <= deg p + deg q" by (rule deg_mult_ring) -next - let ?s = "(%i. coeff p i * coeff q (deg p + deg q - i))" - assume nz: "p ~= 0" "q ~= 0" - have less_add_diff: "!!(k::nat) n m. k < n ==> m < n + m - k" by arith - show "deg p + deg q <= deg (p * q)" - proof (rule deg_belowI, simp) - have "setsum ?s {.. deg p + deg q} - = setsum ?s ({.. deg p(} Un {deg p .. deg p + deg q})" - by (simp only: ivl_disj_un_one) - also have "... = setsum ?s {deg p .. deg p + deg q}" - by (simp add: setsum_Un_disjoint ivl_disj_int_one - setsum_0 deg_aboveD less_add_diff) - also have "... = setsum ?s ({deg p} Un {)deg p .. deg p + deg q})" - by (simp only: ivl_disj_un_singleton) - also have "... = coeff p (deg p) * coeff q (deg q)" - by (simp add: setsum_Un_disjoint ivl_disj_int_singleton - setsum_0 deg_aboveD) - finally have "setsum ?s {.. deg p + deg q} - = coeff p (deg p) * coeff q (deg q)" . - with nz show "setsum ?s {.. deg p + deg q} ~= 0" - by (simp add: integral_iff lcoeff_nonzero) - qed - qed - -lemma coeff_natsum: - "((coeff (setsum p A) k)::'a::ring) = - setsum (%i. coeff (p i) k) A" -proof (cases "finite A") - case True then show ?thesis by induct auto -next - case False then show ?thesis by (simp add: setsum_def) -qed -(* Instance of a more general result!!! *) - -(* -lemma coeff_natsum: - "((coeff (setsum p {..n::nat}) k)::'a::ring) = - setsum (%i. coeff (p i) k) {..n}" -by (induct n) auto -*) - -lemma up_repr: - "setsum (%i. monom (coeff p i) i) {..deg (p::'a::ring up)} = p" -proof (rule up_eqI) - let ?s = "(%i. monom (coeff p i) i)" - fix k - show "coeff (setsum ?s {..deg p}) k = coeff p k" - proof (cases "k <= deg p") - case True - hence "coeff (setsum ?s {..deg p}) k = - coeff (setsum ?s ({..k} Un {)k..deg p})) k" - by (simp only: ivl_disj_un_one) - also from True - have "... = coeff (setsum ?s {..k}) k" - by (simp add: setsum_Un_disjoint ivl_disj_int_one order_less_imp_not_eq2 - setsum_0 coeff_natsum ) - also - have "... = coeff (setsum ?s ({..k(} Un {k})) k" - by (simp only: ivl_disj_un_singleton) - also have "... = coeff p k" - by (simp add: setsum_Un_disjoint ivl_disj_int_singleton - setsum_0 coeff_natsum deg_aboveD) - finally show ?thesis . - next - case False - hence "coeff (setsum ?s {..deg p}) k = - coeff (setsum ?s ({..deg p(} Un {deg p})) k" - by (simp only: ivl_disj_un_singleton) - also from False have "... = coeff p k" - by (simp add: setsum_Un_disjoint ivl_disj_int_singleton - setsum_0 coeff_natsum deg_aboveD) - finally show ?thesis . - qed -qed - -lemma up_repr_le: - "deg (p::'a::ring up) <= n ==> setsum (%i. monom (coeff p i) i) {..n} = p" -proof - - let ?s = "(%i. monom (coeff p i) i)" - assume "deg p <= n" - then have "setsum ?s {..n} = setsum ?s ({..deg p} Un {)deg p..n})" - by (simp only: ivl_disj_un_one) - also have "... = setsum ?s {..deg p}" - by (simp add: setsum_Un_disjoint ivl_disj_int_one - setsum_0 deg_aboveD) - also have "... = p" by (rule up_repr) - finally show ?thesis . -qed - -instance up :: ("domain") "domain" -proof - show "1 ~= (0::'a up)" - proof (* notI is applied here *) - assume "1 = (0::'a up)" - hence "coeff 1 0 = (coeff 0 0::'a)" by simp - hence "1 = (0::'a)" by simp - with one_not_zero show "False" by contradiction - qed -next - fix p q :: "'a::domain up" - assume pq: "p * q = 0" - show "p = 0 | q = 0" - proof (rule classical) - assume c: "~ (p = 0 | q = 0)" - then have "deg p + deg q = deg (p * q)" by simp - also from pq have "... = 0" by simp - finally have "deg p + deg q = 0" . - then have f1: "deg p = 0 & deg q = 0" by simp - from f1 have "p = setsum (%i. (monom (coeff p i) i)) {..0}" - by (simp only: up_repr_le) - also have "... = monom (coeff p 0) 0" by simp - finally have p: "p = monom (coeff p 0) 0" . - from f1 have "q = setsum (%i. (monom (coeff q i) i)) {..0}" - by (simp only: up_repr_le) - also have "... = monom (coeff q 0) 0" by simp - finally have q: "q = monom (coeff q 0) 0" . - have "coeff p 0 * coeff q 0 = coeff (p * q) 0" by simp - also from pq have "... = 0" by simp - finally have "coeff p 0 * coeff q 0 = 0" . - then have "coeff p 0 = 0 | coeff q 0 = 0" by (simp only: integral_iff) - with p q show "p = 0 | q = 0" by fastsimp - qed -qed - -lemma monom_inj_zero: - "(monom a n = 0) = (a = 0)" -proof - - have "(monom a n = 0) = (monom a n = monom 0 n)" by simp - also have "... = (a = 0)" by (simp add: monom_inj del: monom_zero) - finally show ?thesis . -qed -(* term order: makes this simpler!!! -lemma smult_integral: - "(a::'a::domain) *s p = 0 ==> a = 0 | p = 0" -by (simp add: monom_mult_is_smult [THEN sym] integral_iff monom_inj_zero) fast -*) -lemma smult_integral: - "(a::'a::domain) *s p = 0 ==> a = 0 | p = 0" -by (simp add: monom_mult_is_smult [THEN sym] integral_iff monom_inj_zero) - -end \ No newline at end of file diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/poly/UnivPoly2.ML --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Algebra/poly/UnivPoly2.ML Wed Apr 30 10:01:35 2003 +0200 @@ -0,0 +1,359 @@ +(* + Degree of polynomials + $Id$ + written by Clemens Ballarin, started 22 January 1997 +*) + +(* +(* Relating degree and bound *) + +Goal "[| bound m f; f n ~= 0 |] ==> n <= m"; +by (force_tac (claset() addDs [inst "m" "n" boundD], + simpset()) 1); +qed "below_bound"; + +goal UnivPoly2.thy "bound (LEAST n. bound n (Rep_UP p)) (Rep_UP p)"; +by (rtac exE 1); +by (rtac LeastI 2); +by (assume_tac 2); +by (res_inst_tac [("a", "Rep_UP p")] CollectD 1); +by (rtac (rewrite_rule [UP_def] Rep_UP) 1); +qed "Least_is_bound"; + +Goalw [coeff_def, deg_def] + "!! p. ALL m. n < m --> coeff m p = 0 ==> deg p <= n"; +by (rtac Least_le 1); +by (Fast_tac 1); +qed "deg_aboveI"; + +Goalw [coeff_def, deg_def] + "(n ~= 0 --> coeff n p ~= 0) ==> n <= deg p"; +by (case_tac "n = 0" 1); +(* Case n=0 *) +by (Asm_simp_tac 1); +(* Case n~=0 *) +by (rotate_tac 1 1); +by (Asm_full_simp_tac 1); +by (rtac below_bound 1); +by (assume_tac 2); +by (rtac Least_is_bound 1); +qed "deg_belowI"; + +Goalw [coeff_def, deg_def] + "deg p < m ==> coeff m p = 0"; +by (rtac exE 1); (* create !! x. *) +by (rtac boundD 2); +by (assume_tac 3); +by (rtac LeastI 2); +by (assume_tac 2); +by (res_inst_tac [("a", "Rep_UP p")] CollectD 1); +by (rtac (rewrite_rule [UP_def] Rep_UP) 1); +qed "deg_aboveD"; + +Goalw [deg_def] + "deg p = Suc y ==> ~ bound y (Rep_UP p)"; +by (rtac not_less_Least 1); +by (Asm_simp_tac 1); +val lemma1 = result(); + +Goalw [deg_def, coeff_def] + "deg p = Suc y ==> coeff (deg p) p ~= 0"; +by (rtac ccontr 1); +by (dtac notnotD 1); +by (cut_inst_tac [("p", "p")] Least_is_bound 1); +by (subgoal_tac "bound y (Rep_UP p)" 1); +(* prove subgoal *) +by (rtac boundI 2); +by (case_tac "Suc y < m" 2); +(* first case *) +by (rtac boundD 2); +by (assume_tac 2); +by (Asm_simp_tac 2); +(* second case *) +by (dtac leI 2); +by (dtac Suc_leI 2); +by (dtac le_anti_sym 2); +by (assume_tac 2); +by (Asm_full_simp_tac 2); +(* end prove subgoal *) +by (fold_goals_tac [deg_def]); +by (dtac lemma1 1); +by (etac notE 1); +by (assume_tac 1); +val lemma2 = result(); + +Goal "deg p ~= 0 ==> coeff (deg p) p ~= 0"; +by (rtac lemma2 1); +by (Full_simp_tac 1); +by (dtac Suc_pred 1); +by (rtac sym 1); +by (Asm_simp_tac 1); +qed "deg_lcoeff"; + +Goal "p ~= 0 ==> coeff (deg p) p ~= 0"; +by (etac contrapos_np 1); +by (case_tac "deg p = 0" 1); +by (blast_tac (claset() addSDs [deg_lcoeff]) 2); +by (rtac up_eqI 1); +by (case_tac "n=0" 1); +by (rotate_tac ~2 1); +by (Asm_full_simp_tac 1); +by (asm_full_simp_tac (simpset() addsimps [deg_aboveD]) 1); +qed "nonzero_lcoeff"; + +Goal "(deg p <= n) = bound n (Rep_UP p)"; +by (rtac iffI 1); +(* ==> *) +by (rtac boundI 1); +by (fold_goals_tac [coeff_def]); +by (rtac deg_aboveD 1); +by (fast_arith_tac 1); +(* <== *) +by (rtac deg_aboveI 1); +by (rewtac coeff_def); +by (Fast_tac 1); +qed "deg_above_is_bound"; + +(* Lemmas on the degree function *) + +Goalw [max_def] + "!! p::'a::ring up. deg (p + q) <= max (deg p) (deg q)"; +by (case_tac "deg p <= deg q" 1); +(* case deg p <= deg q *) +by (rtac deg_aboveI 1); +by (Asm_simp_tac 1); +by (strip_tac 1); +by (dtac le_less_trans 1); +by (assume_tac 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); +(* case deg p > deg q *) +by (rtac deg_aboveI 1); +by (Asm_simp_tac 1); +by (dtac not_leE 1); +by (strip_tac 1); +by (dtac less_trans 1); +by (assume_tac 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); +qed "deg_add"; + +Goal "!!p::('a::ring up). deg p < deg q ==> deg (p + q) = deg q"; +by (rtac order_antisym 1); +by (rtac le_trans 1); +by (rtac deg_add 1); +by (Asm_simp_tac 1); +by (rtac deg_belowI 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD, deg_lcoeff]) 1); +qed "deg_add_equal"; + +Goal "deg (monom m::'a::ring up) <= m"; +by (asm_simp_tac + (simpset() addsimps [deg_aboveI, less_not_refl2 RS not_sym]) 1); +qed "deg_monom_ring"; + +Goal "deg (monom m::'a::domain up) = m"; +by (rtac le_anti_sym 1); +(* <= *) +by (rtac deg_monom_ring 1); +(* >= *) +by (asm_simp_tac + (simpset() addsimps [deg_belowI, less_not_refl2 RS not_sym]) 1); +qed "deg_monom"; + +Goal "!! a::'a::ring. deg (const a) = 0"; +by (rtac le_anti_sym 1); +by (rtac deg_aboveI 1); +by (simp_tac (simpset() addsimps [less_not_refl2]) 1); +by (rtac deg_belowI 1); +by (simp_tac (simpset() addsimps [less_not_refl2]) 1); +qed "deg_const"; + +Goal "deg (0::'a::ringS up) = 0"; +by (rtac le_anti_sym 1); +by (rtac deg_aboveI 1); +by (Simp_tac 1); +by (rtac deg_belowI 1); +by (Simp_tac 1); +qed "deg_zero"; + +Goal "deg (<1>::'a::ring up) = 0"; +by (rtac le_anti_sym 1); +by (rtac deg_aboveI 1); +by (simp_tac (simpset() addsimps [less_not_refl2]) 1); +by (rtac deg_belowI 1); +by (Simp_tac 1); +qed "deg_one"; + +Goal "!!p::('a::ring) up. deg (-p) = deg p"; +by (rtac le_anti_sym 1); +(* <= *) +by (simp_tac (simpset() addsimps [deg_aboveI, deg_aboveD]) 1); +by (simp_tac (simpset() addsimps [deg_belowI, deg_lcoeff, uminus_monom_neq]) 1); +qed "deg_uminus"; + +Addsimps [deg_monom, deg_const, deg_zero, deg_one, deg_uminus]; + +Goal + "!! a::'a::ring. deg (a *s p) <= (if a = 0 then 0 else deg p)"; +by (case_tac "a = 0" 1); +by (REPEAT (asm_simp_tac (simpset() addsimps [deg_aboveI, deg_aboveD]) 1)); +qed "deg_smult_ring"; + +Goal + "!! a::'a::domain. deg (a *s p) = (if a = 0 then 0 else deg p)"; +by (rtac le_anti_sym 1); +by (rtac deg_smult_ring 1); +by (case_tac "a = 0" 1); +by (REPEAT (asm_simp_tac (simpset() addsimps [deg_belowI, deg_lcoeff]) 1)); +qed "deg_smult"; + +Goal + "!! p::'a::ring up. [| deg p + deg q < k |] ==> \ +\ coeff i p * coeff (k - i) q = 0"; +by (simp_tac (simpset() addsimps [coeff_def]) 1); +by (rtac bound_mult_zero 1); +by (assume_tac 3); +by (simp_tac (simpset() addsimps [deg_above_is_bound RS sym]) 1); +by (simp_tac (simpset() addsimps [deg_above_is_bound RS sym]) 1); +qed "deg_above_mult_zero"; + +Goal + "!! p::'a::ring up. deg (p * q) <= deg p + deg q"; +by (rtac deg_aboveI 1); +by (asm_simp_tac (simpset() addsimps [deg_above_mult_zero]) 1); +qed "deg_mult_ring"; + +goal Main.thy + "!!k::nat. k < n ==> m < n + m - k"; +by (arith_tac 1); +qed "less_add_diff"; + +Goal "!!p. coeff n p ~= 0 ==> n <= deg p"; +(* More general than deg_belowI, and simplifies the next proof! *) +by (rtac deg_belowI 1); +by (Fast_tac 1); +qed "deg_below2I"; + +Goal + "!! p::'a::domain up. \ +\ [| p ~= 0; q ~= 0 |] ==> deg (p * q) = deg p + deg q"; +by (rtac le_anti_sym 1); +by (rtac deg_mult_ring 1); +(* deg p + deg q <= deg (p * q) *) +by (rtac deg_below2I 1); +by (Simp_tac 1); +(* +by (rtac conjI 1); +by (rtac impI 1); +*) +by (res_inst_tac [("m", "deg p"), ("n", "deg p + deg q")] SUM_extend 1); +by (rtac le_add1 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD]) 1); +by (res_inst_tac [("m", "deg p"), ("n", "deg p")] SUM_extend_below 1); +by (rtac le_refl 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); +by (asm_simp_tac (simpset() addsimps [nonzero_lcoeff]) 1); +(* +by (rtac impI 1); +by (res_inst_tac [("m", "deg p"), ("n", "deg p + deg q")] SUM_extend 1); +by (rtac le_add1 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); +by (res_inst_tac [("m", "deg p"), ("n", "deg p")] SUM_extend_below 1); +by (rtac le_refl 1); +by (asm_simp_tac (simpset() addsimps [deg_aboveD, less_add_diff]) 1); +by (asm_simp_tac (simpset() addsimps [nonzero_lcoeff]) 1); +*) +qed "deg_mult"; + +Addsimps [deg_smult, deg_mult]; + +(* Representation theorems about polynomials *) + +goal PolyRing.thy + "!! p::nat=>'a::ring up. \ +\ coeff k (setsum p {..n}) = setsum (%i. coeff k (p i)) {..n}"; +by (induct_tac "n" 1); +by Auto_tac; +qed "coeff_SUM"; + +goal UnivPoly2.thy + "!! f::(nat=>'a::ring). \ +\ bound n f ==> setsum (%i. if i = x then f i else 0) {..n} = f x"; +by (simp_tac (simpset() addsimps [SUM_if_singleton]) 1); +by (auto_tac + (claset() addDs [not_leE], + simpset())); +qed "bound_SUM_if"; + +Goal + "!! p::'a::ring up. deg p <= n ==> \ +\ setsum (%i. coeff i p *s monom i) {..n} = p"; +by (rtac up_eqI 1); +by (simp_tac (simpset() addsimps [coeff_SUM]) 1); +by (rtac trans 1); +by (res_inst_tac [("x", "na")] bound_SUM_if 2); +by (full_simp_tac (simpset() addsimps [deg_above_is_bound, coeff_def]) 2); +by (rtac SUM_cong 1); +by (rtac refl 1); +by (Asm_simp_tac 1); +qed "up_repr"; + +Goal + "!! p::'a::ring up. [| deg p <= n; P p |] ==> \ +\ P (setsum (%i. coeff i p *s monom i) {..n})"; +by (asm_simp_tac (simpset() addsimps [up_repr]) 1); +qed "up_reprD"; + +Goal + "!! p::'a::ring up. \ +\ [| deg p <= n; P (setsum (%i. coeff i p *s monom i) {..n}) |] \ +\ ==> P p"; +by (asm_full_simp_tac (simpset() addsimps [up_repr]) 1); +qed "up_repr2D"; + +(* +Goal + "!! p::'a::ring up. [| deg p <= n; deg q <= m |] ==> \ +\ (SUM n (%i. coeff i p *s monom i) = SUM m (%i. coeff i q *s monom i)) \ +\ = (coeff k f = coeff k g) +... +qed "up_unique"; +*) + +(* Polynomials over integral domains are again integral domains *) + +Goal "!!p::'a::domain up. p * q = 0 ==> p = 0 | q = 0"; +by (rtac classical 1); +by (subgoal_tac "deg p = 0 & deg q = 0" 1); +by (res_inst_tac [("p", "p"), ("n", "0")] up_repr2D 1); +by (Asm_simp_tac 1); +by (res_inst_tac [("p", "q"), ("n", "0")] up_repr2D 1); +by (Asm_simp_tac 1); +by (subgoal_tac "coeff 0 p = 0 | coeff 0 q = 0" 1); +by (force_tac (claset() addIs [up_eqI], simpset()) 1); +by (rtac integral 1); +by (subgoal_tac "coeff 0 (p * q) = 0" 1); +by (Asm_simp_tac 2); +by (Full_simp_tac 1); +by (dres_inst_tac [("f", "deg")] arg_cong 1); +by (Asm_full_simp_tac 1); +qed "up_integral"; + +Goal "!! a::'a::domain. a *s p = 0 ==> a = 0 | p = 0"; +by (full_simp_tac (simpset() addsimps [const_mult_is_smult RS sym]) 1); +by (dtac up_integral 1); +by Auto_tac; +by (rtac (const_inj RS injD) 1); +by (Simp_tac 1); +qed "smult_integral"; +*) + +(* Divisibility and degree *) + +Goalw [dvd_def] + "!! p::'a::domain up. [| p dvd q; q ~= 0 |] ==> deg p <= deg q"; +by (etac exE 1); +by (hyp_subst_tac 1); +by (case_tac "p = 0" 1); +by (case_tac "k = 0" 2); +by Auto_tac; +qed "dvd_imp_deg"; diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/poly/UnivPoly2.thy --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/HOL/Algebra/poly/UnivPoly2.thy Wed Apr 30 10:01:35 2003 +0200 @@ -0,0 +1,779 @@ +(* + Title: Univariate Polynomials + Id: $Id$ + Author: Clemens Ballarin, started 9 December 1996 + Copyright: Clemens Ballarin +*) + +header {* Univariate Polynomials *} + +theory UnivPoly2 = Abstract: + +(* already proved in Finite_Set.thy + +lemma setsum_cong: + "[| A = B; !!i. i : B ==> f i = g i |] ==> setsum f A = setsum g B" +proof - + assume prems: "A = B" "!!i. i : B ==> f i = g i" + show ?thesis + proof (cases "finite B") + case True + then have "!!A. [| A = B; !!i. i : B ==> f i = g i |] ==> + setsum f A = setsum g B" + proof induct + case empty thus ?case by simp + next + case insert thus ?case by simp + qed + with prems show ?thesis by simp + next + case False with prems show ?thesis by (simp add: setsum_def) + qed +qed +*) + +(* Instruct simplifier to simplify assumptions introduced by congs. + This makes setsum_cong more convenient to use, because assumptions + like i:{m..n} get simplified (to m <= i & i <= n). *) + +ML_setup {* + +Addcongs [thm "setsum_cong"]; +Context.>> (fn thy => (simpset_ref_of thy := + simpset_of thy setsubgoaler asm_full_simp_tac; thy)) *} + +section {* Definition of type up *} + +constdefs + bound :: "[nat, nat => 'a::zero] => bool" + "bound n f == (ALL i. n < i --> f i = 0)" + +lemma boundI [intro!]: "[| !! m. n < m ==> f m = 0 |] ==> bound n f" +proof (unfold bound_def) +qed fast + +lemma boundE [elim?]: "[| bound n f; (!! m. n < m ==> f m = 0) ==> P |] ==> P" +proof (unfold bound_def) +qed fast + +lemma boundD [dest]: "[| bound n f; n < m |] ==> f m = 0" +proof (unfold bound_def) +qed fast + +lemma bound_below: + assumes bound: "bound m f" and nonzero: "f n ~= 0" shows "n <= m" +proof (rule classical) + assume "~ ?thesis" + then have "m < n" by arith + with bound have "f n = 0" .. + with nonzero show ?thesis by contradiction +qed + +typedef (UP) + ('a) up = "{f :: nat => 'a::zero. EX n. bound n f}" +by (rule+) (* Question: what does trace_rule show??? *) + +section {* Constants *} + +consts + coeff :: "['a up, nat] => ('a::zero)" + monom :: "['a::zero, nat] => 'a up" ("(3_*X^/_)" [71, 71] 70) + "*s" :: "['a::{zero, times}, 'a up] => 'a up" (infixl 70) + +defs + coeff_def: "coeff p n == Rep_UP p n" + monom_def: "monom a n == Abs_UP (%i. if i=n then a else 0)" + smult_def: "a *s p == Abs_UP (%i. a * Rep_UP p i)" + +lemma coeff_bound_ex: "EX n. bound n (coeff p)" +proof - + have "(%n. coeff p n) : UP" by (simp add: coeff_def Rep_UP) + then obtain n where "bound n (coeff p)" by (unfold UP_def) fast + then show ?thesis .. +qed + +lemma bound_coeff_obtain: + assumes prem: "(!!n. bound n (coeff p) ==> P)" shows "P" +proof - + have "(%n. coeff p n) : UP" by (simp add: coeff_def Rep_UP) + then obtain n where "bound n (coeff p)" by (unfold UP_def) fast + with prem show P . +qed + +text {* Ring operations *} + +instance up :: (zero) zero .. +instance up :: (one) one .. +instance up :: (plus) plus .. +instance up :: (minus) minus .. +instance up :: (times) times .. +instance up :: (inverse) inverse .. +instance up :: (power) power .. + +defs + up_add_def: "p + q == Abs_UP (%n. Rep_UP p n + Rep_UP q n)" + up_mult_def: "p * q == Abs_UP (%n::nat. setsum + (%i. Rep_UP p i * Rep_UP q (n-i)) {..n})" + up_zero_def: "0 == monom 0 0" + up_one_def: "1 == monom 1 0" + up_uminus_def:"- p == (- 1) *s p" + (* easier to use than "Abs_UP (%i. - Rep_UP p i)" *) + (* note: - 1 is different from -1; latter is of class number *) + + up_minus_def: "(a::'a::{plus, minus} up) - b == a + (-b)" + up_inverse_def: "inverse (a::'a::{zero, one, times, inverse} up) == + (if a dvd 1 then THE x. a*x = 1 else 0)" + up_divide_def: "(a::'a::{times, inverse} up) / b == a * inverse b" + up_power_def: "(a::'a::{one, times, power} up) ^ n == + nat_rec 1 (%u b. b * a) n" + +subsection {* Effect of operations on coefficients *} + +lemma coeff_monom [simp]: "coeff (monom a m) n = (if m=n then a else 0)" +proof - + have "(%n. if n = m then a else 0) : UP" + using UP_def by force + from this show ?thesis + by (simp add: coeff_def monom_def Abs_UP_inverse Rep_UP) +qed + +lemma coeff_zero [simp]: "coeff 0 n = 0" +proof (unfold up_zero_def) +qed simp + +lemma coeff_one [simp]: "coeff 1 n = (if n=0 then 1 else 0)" +proof (unfold up_one_def) +qed simp + +(* term order +lemma coeff_smult [simp]: "coeff (a *s p) n = (a::'a::ring) * coeff p n" +proof - + have "!!f. f : UP ==> (%n. a * f n) : UP" + by (unfold UP_def) (force simp add: ring_simps) +*) (* this force step is slow *) +(* then show ?thesis + apply (simp add: coeff_def smult_def Abs_UP_inverse Rep_UP) +qed +*) +lemma coeff_smult [simp]: "coeff (a *s p) n = (a::'a::ring) * coeff p n" +proof - + have "Rep_UP p : UP ==> (%n. a * Rep_UP p n) : UP" + by (unfold UP_def) (force simp add: ring_simps) + (* this force step is slow *) + then show ?thesis + by (simp add: coeff_def smult_def Abs_UP_inverse Rep_UP) +qed + +lemma coeff_add [simp]: "coeff (p+q) n = (coeff p n + coeff q n::'a::ring)" +proof - + { + fix f g + assume fup: "(f::nat=>'a::ring) : UP" and gup: "(g::nat=>'a::ring) : UP" + have "(%i. f i + g i) : UP" + proof - + from fup obtain n where boundn: "bound n f" + by (unfold UP_def) fast + from gup obtain m where boundm: "bound m g" + by (unfold UP_def) fast + have "bound (max n m) (%i. (f i + g i))" + proof + fix i + assume "max n m < i" + with boundn and boundm show "f i + g i = 0" + by (fastsimp simp add: ring_simps) + qed + then show "(%i. (f i + g i)) : UP" + by (unfold UP_def) fast + qed + } + then show ?thesis + by (simp add: coeff_def up_add_def Abs_UP_inverse Rep_UP) +qed + +lemma coeff_mult [simp]: + "coeff (p * q) n = (setsum (%i. coeff p i * coeff q (n-i)) {..n}::'a::ring)" +proof - + { + fix f g + assume fup: "(f::nat=>'a::ring) : UP" and gup: "(g::nat=>'a::ring) : UP" + have "(%n. setsum (%i. f i * g (n-i)) {..n}) : UP" + proof - + from fup obtain n where "bound n f" + by (unfold UP_def) fast + from gup obtain m where "bound m g" + by (unfold UP_def) fast + have "bound (n + m) (%n. setsum (%i. f i * g (n-i)) {..n})" + proof + fix k + assume bound: "n + m < k" + { + fix i + have "f i * g (k-i) = 0" + proof cases + assume "n < i" + show ?thesis by (auto! simp add: ring_simps) + next + assume "~ (n < i)" + with bound have "m < k-i" by arith + then show ?thesis by (auto! simp add: ring_simps) + qed + } + then show "setsum (%i. f i * g (k-i)) {..k} = 0" + by (simp add: ring_simps) + qed + then show "(%n. setsum (%i. f i * g (n-i)) {..n}) : UP" + by (unfold UP_def) fast + qed + } + then show ?thesis + by (simp add: coeff_def up_mult_def Abs_UP_inverse Rep_UP) +qed + +lemma coeff_uminus [simp]: "coeff (-p) n = (-coeff p n::'a::ring)" +by (unfold up_uminus_def) (simp add: ring_simps) + +(* Other lemmas *) + +lemma up_eqI: assumes prem: "(!! n. coeff p n = coeff q n)" shows "p = q" +proof - + have "p = Abs_UP (%u. Rep_UP p u)" by (simp add: Rep_UP_inverse) + also from prem have "... = Abs_UP (Rep_UP q)" by (simp only: coeff_def) + also have "... = q" by (simp add: Rep_UP_inverse) + finally show ?thesis . +qed + +(* ML_setup {* Addsimprocs [ring_simproc] *} *) + +instance up :: (ring) ring +proof + fix p q r :: "'a::ring up" + fix n + show "(p + q) + r = p + (q + r)" + by (rule up_eqI) simp + show "0 + p = p" + by (rule up_eqI) simp + show "(-p) + p = 0" + by (rule up_eqI) simp + show "p + q = q + p" + by (rule up_eqI) simp + show "(p * q) * r = p * (q * r)" + proof (rule up_eqI) + fix n + { + fix k and a b c :: "nat=>'a::ring" + have "k <= n ==> + setsum (%j. setsum (%i. a i * b (j-i)) {..j} * c (n-j)) {..k} = + setsum (%j. a j * setsum (%i. b i * c (n-j-i)) {..k-j}) {..k}" + (is "_ ==> ?eq k") + proof (induct k) + case 0 show ?case by simp + next + case (Suc k) + then have "k <= n" by arith + then have "?eq k" by (rule Suc) + then show ?case + by (simp add: Suc_diff_le natsum_ldistr) + qed + } + then show "coeff ((p * q) * r) n = coeff (p * (q * r)) n" + by simp + qed + show "1 * p = p" + proof (rule up_eqI) + fix n + show "coeff (1 * p) n = coeff p n" + proof (cases n) + case 0 then show ?thesis by simp + next + case Suc then show ?thesis by (simp del: natsum_Suc add: natsum_Suc2) + qed + qed + show "(p + q) * r = p * r + q * r" + by (rule up_eqI) simp + show "p * q = q * p" + proof (rule up_eqI) + fix n + { + fix k + fix a b :: "nat=>'a::ring" + have "k <= n ==> + setsum (%i. a i * b (n-i)) {..k} = + setsum (%i. a (k-i) * b (i+n-k)) {..k}" + (is "_ ==> ?eq k") + proof (induct k) + case 0 show ?case by simp + next + case (Suc k) then show ?case by (subst natsum_Suc2) simp + qed + } + then show "coeff (p * q) n = coeff (q * p) n" + by simp + qed + + show "p - q = p + (-q)" + by (simp add: up_minus_def) + show "inverse p = (if p dvd 1 then THE x. p*x = 1 else 0)" + by (simp add: up_inverse_def) + show "p / q = p * inverse q" + by (simp add: up_divide_def) + show "p ^ n = nat_rec 1 (%u b. b * p) n" + by (simp add: up_power_def) + qed + +(* Further properties of monom *) + +lemma monom_zero [simp]: + "monom 0 n = 0" + by (simp add: monom_def up_zero_def) +(* term order: application of coeff_mult goes wrong: rule not symmetric +lemma monom_mult_is_smult: + "monom (a::'a::ring) 0 * p = a *s p" +proof (rule up_eqI) + fix k + show "coeff (monom a 0 * p) k = coeff (a *s p) k" + proof (cases k) + case 0 then show ?thesis by simp + next + case Suc then show ?thesis by simp + qed +qed +*) +ML_setup {* Delsimprocs [ring_simproc] *} + +lemma monom_mult_is_smult: + "monom (a::'a::ring) 0 * p = a *s p" +proof (rule up_eqI) + fix k + have "coeff (p * monom a 0) k = coeff (a *s p) k" + proof (cases k) + case 0 then show ?thesis by simp ring + next + case Suc then show ?thesis by (simp add: ring_simps) ring + qed + then show "coeff (monom a 0 * p) k = coeff (a *s p) k" by ring +qed + +ML_setup {* Addsimprocs [ring_simproc] *} + +lemma monom_add [simp]: + "monom (a + b) n = monom (a::'a::ring) n + monom b n" +by (rule up_eqI) simp + +lemma monom_mult_smult: + "monom (a * b) n = a *s monom (b::'a::ring) n" +by (rule up_eqI) simp + +lemma monom_uminus [simp]: + "monom (-a) n = - monom (a::'a::ring) n" +by (rule up_eqI) simp + +lemma monom_one [simp]: + "monom 1 0 = 1" +by (simp add: up_one_def) + +lemma monom_inj: + "(monom a n = monom b n) = (a = b)" +proof + assume "monom a n = monom b n" + then have "coeff (monom a n) n = coeff (monom b n) n" by simp + then show "a = b" by simp +next + assume "a = b" then show "monom a n = monom b n" by simp +qed + +(* Properties of *s: + Polynomials form a module *) + +lemma smult_l_distr: + "(a + b::'a::ring) *s p = a *s p + b *s p" +by (rule up_eqI) simp + +lemma smult_r_distr: + "(a::'a::ring) *s (p + q) = a *s p + a *s q" +by (rule up_eqI) simp + +lemma smult_assoc1: + "(a * b::'a::ring) *s p = a *s (b *s p)" +by (rule up_eqI) simp + +lemma smult_one [simp]: + "(1::'a::ring) *s p = p" +by (rule up_eqI) simp + +(* Polynomials form an algebra *) + +ML_setup {* Delsimprocs [ring_simproc] *} + +lemma smult_assoc2: + "(a *s p) * q = (a::'a::ring) *s (p * q)" +by (rule up_eqI) (simp add: natsum_rdistr m_assoc) +(* Simproc fails. *) + +ML_setup {* Addsimprocs [ring_simproc] *} + +(* the following can be derived from the above ones, + for generality reasons, it is therefore done *) + +lemma smult_l_null [simp]: + "(0::'a::ring) *s p = 0" +proof - + fix a + have "0 *s p = (0 *s p + a *s p) + - (a *s p)" by simp + also have "... = (0 + a) *s p + - (a *s p)" by (simp only: smult_l_distr) + also have "... = 0" by simp + finally show ?thesis . +qed + +lemma smult_r_null [simp]: + "(a::'a::ring) *s 0 = 0"; +proof - + fix p + have "a *s 0 = (a *s 0 + a *s p) + - (a *s p)" by simp + also have "... = a *s (0 + p) + - (a *s p)" by (simp only: smult_r_distr) + also have "... = 0" by simp + finally show ?thesis . +qed + +lemma smult_l_minus: + "(-a::'a::ring) *s p = - (a *s p)" +proof - + have "(-a) *s p = (-a *s p + a *s p) + -(a *s p)" by simp + also have "... = (-a + a) *s p + -(a *s p)" by (simp only: smult_l_distr) + also have "... = -(a *s p)" by simp + finally show ?thesis . +qed + +lemma smult_r_minus: + "(a::'a::ring) *s (-p) = - (a *s p)" +proof - + have "a *s (-p) = (a *s -p + a *s p) + -(a *s p)" by simp + also have "... = a *s (-p + p) + -(a *s p)" by (simp only: smult_r_distr) + also have "... = -(a *s p)" by simp + finally show ?thesis . +qed + +section {* The degree function *} + +constdefs + deg :: "('a::zero) up => nat" + "deg p == LEAST n. bound n (coeff p)" + +lemma deg_aboveI: + "(!!m. n < m ==> coeff p m = 0) ==> deg p <= n" +by (unfold deg_def) (fast intro: Least_le) + +lemma deg_aboveD: + assumes prem: "deg p < m" shows "coeff p m = 0" +proof - + obtain n where "bound n (coeff p)" by (rule bound_coeff_obtain) + then have "bound (deg p) (coeff p)" by (unfold deg_def, rule LeastI) + then show "coeff p m = 0" by (rule boundD) +qed + +lemma deg_belowI: + assumes prem: "n ~= 0 ==> coeff p n ~= 0" shows "n <= deg p" +(* logically, this is a slightly stronger version of deg_aboveD *) +proof (cases "n=0") + case True then show ?thesis by simp +next + case False then have "coeff p n ~= 0" by (rule prem) + then have "~ deg p < n" by (fast dest: deg_aboveD) + then show ?thesis by arith +qed + +lemma lcoeff_nonzero_deg: + assumes deg: "deg p ~= 0" shows "coeff p (deg p) ~= 0" +proof - + obtain m where "deg p <= m" and m_coeff: "coeff p m ~= 0" + proof - + have minus: "!!(n::nat) m. n ~= 0 ==> (n - Suc 0 < m) = (n <= m)" + by arith (* make public?, why does proof not work with "1" *) + from deg have "deg p - 1 < (LEAST n. bound n (coeff p))" + by (unfold deg_def) arith + then have "~ bound (deg p - 1) (coeff p)" by (rule not_less_Least) + then have "EX m. deg p - 1 < m & coeff p m ~= 0" + by (unfold bound_def) fast + then have "EX m. deg p <= m & coeff p m ~= 0" by (simp add: deg minus) + then show ?thesis by auto + qed + with deg_belowI have "deg p = m" by fastsimp + with m_coeff show ?thesis by simp +qed + +lemma lcoeff_nonzero_nonzero: + assumes deg: "deg p = 0" and nonzero: "p ~= 0" shows "coeff p 0 ~= 0" +proof - + have "EX m. coeff p m ~= 0" + proof (rule classical) + assume "~ ?thesis" + then have "p = 0" by (auto intro: up_eqI) + with nonzero show ?thesis by contradiction + qed + then obtain m where coeff: "coeff p m ~= 0" .. + then have "m <= deg p" by (rule deg_belowI) + then have "m = 0" by (simp add: deg) + with coeff show ?thesis by simp +qed + +lemma lcoeff_nonzero: + "p ~= 0 ==> coeff p (deg p) ~= 0" +proof (cases "deg p = 0") + case True + assume "p ~= 0" + with True show ?thesis by (simp add: lcoeff_nonzero_nonzero) +next + case False + assume "p ~= 0" + with False show ?thesis by (simp add: lcoeff_nonzero_deg) +qed + +lemma deg_eqI: + "[| !!m. n < m ==> coeff p m = 0; + !!n. n ~= 0 ==> coeff p n ~= 0|] ==> deg p = n" +by (fast intro: le_anti_sym deg_aboveI deg_belowI) + +(* Degree and polynomial operations *) + +lemma deg_add [simp]: + "deg ((p::'a::ring up) + q) <= max (deg p) (deg q)" +proof (cases "deg p <= deg q") + case True show ?thesis by (rule deg_aboveI) (simp add: True deg_aboveD) +next + case False show ?thesis by (rule deg_aboveI) (simp add: False deg_aboveD) +qed + +lemma deg_monom_ring: + "deg (monom a n::'a::ring up) <= n" +by (rule deg_aboveI) simp + +lemma deg_monom [simp]: + "a ~= 0 ==> deg (monom a n::'a::ring up) = n" +by (fastsimp intro: le_anti_sym deg_aboveI deg_belowI) + +lemma deg_const [simp]: + "deg (monom (a::'a::ring) 0) = 0" +proof (rule le_anti_sym) + show "deg (monom a 0) <= 0" by (rule deg_aboveI) simp +next + show "0 <= deg (monom a 0)" by (rule deg_belowI) simp +qed + +lemma deg_zero [simp]: + "deg 0 = 0" +proof (rule le_anti_sym) + show "deg 0 <= 0" by (rule deg_aboveI) simp +next + show "0 <= deg 0" by (rule deg_belowI) simp +qed + +lemma deg_one [simp]: + "deg 1 = 0" +proof (rule le_anti_sym) + show "deg 1 <= 0" by (rule deg_aboveI) simp +next + show "0 <= deg 1" by (rule deg_belowI) simp +qed + +lemma uminus_monom: + "!!a::'a::ring. (-a = 0) = (a = 0)" +proof + fix a::"'a::ring" + assume "a = 0" + then show "-a = 0" by simp +next + fix a::"'a::ring" + assume "- a = 0" + then have "-(- a) = 0" by simp + then show "a = 0" by simp +qed + +lemma deg_uminus [simp]: + "deg (-p::('a::ring) up) = deg p" +proof (rule le_anti_sym) + show "deg (- p) <= deg p" by (simp add: deg_aboveI deg_aboveD) +next + show "deg p <= deg (- p)" + by (simp add: deg_belowI lcoeff_nonzero_deg uminus_monom) +qed + +lemma deg_smult_ring: + "deg ((a::'a::ring) *s p) <= (if a = 0 then 0 else deg p)" +proof (cases "a = 0") +qed (simp add: deg_aboveI deg_aboveD)+ + +lemma deg_smult [simp]: + "deg ((a::'a::domain) *s p) = (if a = 0 then 0 else deg p)" +proof (rule le_anti_sym) + show "deg (a *s p) <= (if a = 0 then 0 else deg p)" by (rule deg_smult_ring) +next + show "(if a = 0 then 0 else deg p) <= deg (a *s p)" + proof (cases "a = 0") + qed (simp, simp add: deg_belowI lcoeff_nonzero_deg integral_iff) +qed + +lemma deg_mult_ring: + "deg (p * q::'a::ring up) <= deg p + deg q" +proof (rule deg_aboveI) + fix m + assume boundm: "deg p + deg q < m" + { + fix k i + assume boundk: "deg p + deg q < k" + then have "coeff p i * coeff q (k - i) = 0" + proof (cases "deg p < i") + case True then show ?thesis by (simp add: deg_aboveD) + next + case False with boundk have "deg q < k - i" by arith + then show ?thesis by (simp add: deg_aboveD) + qed + } + (* This is similar to bound_mult_zero and deg_above_mult_zero in the old + proofs. *) + with boundm show "coeff (p * q) m = 0" by simp +qed + +lemma deg_mult [simp]: + "[| (p::'a::domain up) ~= 0; q ~= 0|] ==> deg (p * q) = deg p + deg q" +proof (rule le_anti_sym) + show "deg (p * q) <= deg p + deg q" by (rule deg_mult_ring) +next + let ?s = "(%i. coeff p i * coeff q (deg p + deg q - i))" + assume nz: "p ~= 0" "q ~= 0" + have less_add_diff: "!!(k::nat) n m. k < n ==> m < n + m - k" by arith + show "deg p + deg q <= deg (p * q)" + proof (rule deg_belowI, simp) + have "setsum ?s {.. deg p + deg q} + = setsum ?s ({.. deg p(} Un {deg p .. deg p + deg q})" + by (simp only: ivl_disj_un_one) + also have "... = setsum ?s {deg p .. deg p + deg q}" + by (simp add: setsum_Un_disjoint ivl_disj_int_one + setsum_0 deg_aboveD less_add_diff) + also have "... = setsum ?s ({deg p} Un {)deg p .. deg p + deg q})" + by (simp only: ivl_disj_un_singleton) + also have "... = coeff p (deg p) * coeff q (deg q)" + by (simp add: setsum_Un_disjoint ivl_disj_int_singleton + setsum_0 deg_aboveD) + finally have "setsum ?s {.. deg p + deg q} + = coeff p (deg p) * coeff q (deg q)" . + with nz show "setsum ?s {.. deg p + deg q} ~= 0" + by (simp add: integral_iff lcoeff_nonzero) + qed + qed + +lemma coeff_natsum: + "((coeff (setsum p A) k)::'a::ring) = + setsum (%i. coeff (p i) k) A" +proof (cases "finite A") + case True then show ?thesis by induct auto +next + case False then show ?thesis by (simp add: setsum_def) +qed +(* Instance of a more general result!!! *) + +(* +lemma coeff_natsum: + "((coeff (setsum p {..n::nat}) k)::'a::ring) = + setsum (%i. coeff (p i) k) {..n}" +by (induct n) auto +*) + +lemma up_repr: + "setsum (%i. monom (coeff p i) i) {..deg (p::'a::ring up)} = p" +proof (rule up_eqI) + let ?s = "(%i. monom (coeff p i) i)" + fix k + show "coeff (setsum ?s {..deg p}) k = coeff p k" + proof (cases "k <= deg p") + case True + hence "coeff (setsum ?s {..deg p}) k = + coeff (setsum ?s ({..k} Un {)k..deg p})) k" + by (simp only: ivl_disj_un_one) + also from True + have "... = coeff (setsum ?s {..k}) k" + by (simp add: setsum_Un_disjoint ivl_disj_int_one order_less_imp_not_eq2 + setsum_0 coeff_natsum ) + also + have "... = coeff (setsum ?s ({..k(} Un {k})) k" + by (simp only: ivl_disj_un_singleton) + also have "... = coeff p k" + by (simp add: setsum_Un_disjoint ivl_disj_int_singleton + setsum_0 coeff_natsum deg_aboveD) + finally show ?thesis . + next + case False + hence "coeff (setsum ?s {..deg p}) k = + coeff (setsum ?s ({..deg p(} Un {deg p})) k" + by (simp only: ivl_disj_un_singleton) + also from False have "... = coeff p k" + by (simp add: setsum_Un_disjoint ivl_disj_int_singleton + setsum_0 coeff_natsum deg_aboveD) + finally show ?thesis . + qed +qed + +lemma up_repr_le: + "deg (p::'a::ring up) <= n ==> setsum (%i. monom (coeff p i) i) {..n} = p" +proof - + let ?s = "(%i. monom (coeff p i) i)" + assume "deg p <= n" + then have "setsum ?s {..n} = setsum ?s ({..deg p} Un {)deg p..n})" + by (simp only: ivl_disj_un_one) + also have "... = setsum ?s {..deg p}" + by (simp add: setsum_Un_disjoint ivl_disj_int_one + setsum_0 deg_aboveD) + also have "... = p" by (rule up_repr) + finally show ?thesis . +qed + +instance up :: ("domain") "domain" +proof + show "1 ~= (0::'a up)" + proof (* notI is applied here *) + assume "1 = (0::'a up)" + hence "coeff 1 0 = (coeff 0 0::'a)" by simp + hence "1 = (0::'a)" by simp + with one_not_zero show "False" by contradiction + qed +next + fix p q :: "'a::domain up" + assume pq: "p * q = 0" + show "p = 0 | q = 0" + proof (rule classical) + assume c: "~ (p = 0 | q = 0)" + then have "deg p + deg q = deg (p * q)" by simp + also from pq have "... = 0" by simp + finally have "deg p + deg q = 0" . + then have f1: "deg p = 0 & deg q = 0" by simp + from f1 have "p = setsum (%i. (monom (coeff p i) i)) {..0}" + by (simp only: up_repr_le) + also have "... = monom (coeff p 0) 0" by simp + finally have p: "p = monom (coeff p 0) 0" . + from f1 have "q = setsum (%i. (monom (coeff q i) i)) {..0}" + by (simp only: up_repr_le) + also have "... = monom (coeff q 0) 0" by simp + finally have q: "q = monom (coeff q 0) 0" . + have "coeff p 0 * coeff q 0 = coeff (p * q) 0" by simp + also from pq have "... = 0" by simp + finally have "coeff p 0 * coeff q 0 = 0" . + then have "coeff p 0 = 0 | coeff q 0 = 0" by (simp only: integral_iff) + with p q show "p = 0 | q = 0" by fastsimp + qed +qed + +lemma monom_inj_zero: + "(monom a n = 0) = (a = 0)" +proof - + have "(monom a n = 0) = (monom a n = monom 0 n)" by simp + also have "... = (a = 0)" by (simp add: monom_inj del: monom_zero) + finally show ?thesis . +qed +(* term order: makes this simpler!!! +lemma smult_integral: + "(a::'a::domain) *s p = 0 ==> a = 0 | p = 0" +by (simp add: monom_mult_is_smult [THEN sym] integral_iff monom_inj_zero) fast +*) +lemma smult_integral: + "(a::'a::domain) *s p = 0 ==> a = 0 | p = 0" +by (simp add: monom_mult_is_smult [THEN sym] integral_iff monom_inj_zero) + +end \ No newline at end of file diff -r 4822d9597d1e -r d3671b878828 src/HOL/Algebra/ringsimp.ML --- a/src/HOL/Algebra/ringsimp.ML Tue Apr 29 12:36:49 2003 +0200 +++ b/src/HOL/Algebra/ringsimp.ML Wed Apr 30 10:01:35 2003 +0200 @@ -56,8 +56,8 @@ (*** Term order for commutative rings ***) fun ring_ord a = - find_index_eq a ["CRing.ring.zero", "CRing.ring.add", "Cring.ring.a_inv", - "CRing.ring.minus", "Group.monoid.one", "Group.semigroup.mult"]; + find_index_eq a ["CRing.ring.zero", "CRing.ring.add", "CRing.a_inv", + "CRing.minus", "Group.monoid.one", "Group.semigroup.mult"]; fun termless_ring (a, b) = (term_lpo ring_ord (a, b) = LESS);