1049 subsection \<open>Generalized product over a set\<close> |
1049 subsection \<open>Generalized product over a set\<close> |
1050 |
1050 |
1051 context comm_monoid_mult |
1051 context comm_monoid_mult |
1052 begin |
1052 begin |
1053 |
1053 |
1054 sublocale setprod: comm_monoid_set times 1 |
1054 sublocale prod: comm_monoid_set times 1 |
1055 defines setprod = setprod.F .. |
1055 defines prod = prod.F .. |
1056 |
1056 |
1057 abbreviation Setprod ("\<Prod>_" [1000] 999) |
1057 abbreviation Prod ("\<Prod>_" [1000] 999) |
1058 where "\<Prod>A \<equiv> setprod (\<lambda>x. x) A" |
1058 where "\<Prod>A \<equiv> prod (\<lambda>x. x) A" |
1059 |
1059 |
1060 end |
1060 end |
1061 |
1061 |
1062 syntax (ASCII) |
1062 syntax (ASCII) |
1063 "_setprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(4PROD _:_./ _)" [0, 51, 10] 10) |
1063 "_prod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(4PROD _:_./ _)" [0, 51, 10] 10) |
1064 syntax |
1064 syntax |
1065 "_setprod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(2\<Prod>_\<in>_./ _)" [0, 51, 10] 10) |
1065 "_prod" :: "pttrn => 'a set => 'b => 'b::comm_monoid_mult" ("(2\<Prod>_\<in>_./ _)" [0, 51, 10] 10) |
1066 translations \<comment> \<open>Beware of argument permutation!\<close> |
1066 translations \<comment> \<open>Beware of argument permutation!\<close> |
1067 "\<Prod>i\<in>A. b" == "CONST setprod (\<lambda>i. b) A" |
1067 "\<Prod>i\<in>A. b" == "CONST prod (\<lambda>i. b) A" |
1068 |
1068 |
1069 text \<open>Instead of @{term"\<Prod>x\<in>{x. P}. e"} we introduce the shorter \<open>\<Prod>x|P. e\<close>.\<close> |
1069 text \<open>Instead of @{term"\<Prod>x\<in>{x. P}. e"} we introduce the shorter \<open>\<Prod>x|P. e\<close>.\<close> |
1070 |
1070 |
1071 syntax (ASCII) |
1071 syntax (ASCII) |
1072 "_qsetprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(4PROD _ |/ _./ _)" [0, 0, 10] 10) |
1072 "_qprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(4PROD _ |/ _./ _)" [0, 0, 10] 10) |
1073 syntax |
1073 syntax |
1074 "_qsetprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(2\<Prod>_ | (_)./ _)" [0, 0, 10] 10) |
1074 "_qprod" :: "pttrn \<Rightarrow> bool \<Rightarrow> 'a \<Rightarrow> 'a" ("(2\<Prod>_ | (_)./ _)" [0, 0, 10] 10) |
1075 translations |
1075 translations |
1076 "\<Prod>x|P. t" => "CONST setprod (\<lambda>x. t) {x. P}" |
1076 "\<Prod>x|P. t" => "CONST prod (\<lambda>x. t) {x. P}" |
1077 |
1077 |
1078 context comm_monoid_mult |
1078 context comm_monoid_mult |
1079 begin |
1079 begin |
1080 |
1080 |
1081 lemma setprod_dvd_setprod: "(\<And>a. a \<in> A \<Longrightarrow> f a dvd g a) \<Longrightarrow> setprod f A dvd setprod g A" |
1081 lemma prod_dvd_prod: "(\<And>a. a \<in> A \<Longrightarrow> f a dvd g a) \<Longrightarrow> prod f A dvd prod g A" |
1082 proof (induct A rule: infinite_finite_induct) |
1082 proof (induct A rule: infinite_finite_induct) |
1083 case infinite |
1083 case infinite |
1084 then show ?case by (auto intro: dvdI) |
1084 then show ?case by (auto intro: dvdI) |
1085 next |
1085 next |
1086 case empty |
1086 case empty |
1087 then show ?case by (auto intro: dvdI) |
1087 then show ?case by (auto intro: dvdI) |
1088 next |
1088 next |
1089 case (insert a A) |
1089 case (insert a A) |
1090 then have "f a dvd g a" and "setprod f A dvd setprod g A" |
1090 then have "f a dvd g a" and "prod f A dvd prod g A" |
1091 by simp_all |
1091 by simp_all |
1092 then obtain r s where "g a = f a * r" and "setprod g A = setprod f A * s" |
1092 then obtain r s where "g a = f a * r" and "prod g A = prod f A * s" |
1093 by (auto elim!: dvdE) |
1093 by (auto elim!: dvdE) |
1094 then have "g a * setprod g A = f a * setprod f A * (r * s)" |
1094 then have "g a * prod g A = f a * prod f A * (r * s)" |
1095 by (simp add: ac_simps) |
1095 by (simp add: ac_simps) |
1096 with insert.hyps show ?case |
1096 with insert.hyps show ?case |
1097 by (auto intro: dvdI) |
1097 by (auto intro: dvdI) |
1098 qed |
1098 qed |
1099 |
1099 |
1100 lemma setprod_dvd_setprod_subset: "finite B \<Longrightarrow> A \<subseteq> B \<Longrightarrow> setprod f A dvd setprod f B" |
1100 lemma prod_dvd_prod_subset: "finite B \<Longrightarrow> A \<subseteq> B \<Longrightarrow> prod f A dvd prod f B" |
1101 by (auto simp add: setprod.subset_diff ac_simps intro: dvdI) |
1101 by (auto simp add: prod.subset_diff ac_simps intro: dvdI) |
1102 |
1102 |
1103 end |
1103 end |
1104 |
1104 |
1105 |
1105 |
1106 subsubsection \<open>Properties in more restricted classes of structures\<close> |
1106 subsubsection \<open>Properties in more restricted classes of structures\<close> |
1107 |
1107 |
1108 context comm_semiring_1 |
1108 context comm_semiring_1 |
1109 begin |
1109 begin |
1110 |
1110 |
1111 lemma dvd_setprod_eqI [intro]: |
1111 lemma dvd_prod_eqI [intro]: |
1112 assumes "finite A" and "a \<in> A" and "b = f a" |
1112 assumes "finite A" and "a \<in> A" and "b = f a" |
1113 shows "b dvd setprod f A" |
1113 shows "b dvd prod f A" |
1114 proof - |
1114 proof - |
1115 from \<open>finite A\<close> have "setprod f (insert a (A - {a})) = f a * setprod f (A - {a})" |
1115 from \<open>finite A\<close> have "prod f (insert a (A - {a})) = f a * prod f (A - {a})" |
1116 by (intro setprod.insert) auto |
1116 by (intro prod.insert) auto |
1117 also from \<open>a \<in> A\<close> have "insert a (A - {a}) = A" |
1117 also from \<open>a \<in> A\<close> have "insert a (A - {a}) = A" |
1118 by blast |
1118 by blast |
1119 finally have "setprod f A = f a * setprod f (A - {a})" . |
1119 finally have "prod f A = f a * prod f (A - {a})" . |
1120 with \<open>b = f a\<close> show ?thesis |
1120 with \<open>b = f a\<close> show ?thesis |
1121 by simp |
1121 by simp |
1122 qed |
1122 qed |
1123 |
1123 |
1124 lemma dvd_setprodI [intro]: "finite A \<Longrightarrow> a \<in> A \<Longrightarrow> f a dvd setprod f A" |
1124 lemma dvd_prodI [intro]: "finite A \<Longrightarrow> a \<in> A \<Longrightarrow> f a dvd prod f A" |
1125 by auto |
1125 by auto |
1126 |
1126 |
1127 lemma setprod_zero: |
1127 lemma prod_zero: |
1128 assumes "finite A" and "\<exists>a\<in>A. f a = 0" |
1128 assumes "finite A" and "\<exists>a\<in>A. f a = 0" |
1129 shows "setprod f A = 0" |
1129 shows "prod f A = 0" |
1130 using assms |
1130 using assms |
1131 proof (induct A) |
1131 proof (induct A) |
1132 case empty |
1132 case empty |
1133 then show ?case by simp |
1133 then show ?case by simp |
1134 next |
1134 next |
1135 case (insert a A) |
1135 case (insert a A) |
1136 then have "f a = 0 \<or> (\<exists>a\<in>A. f a = 0)" by simp |
1136 then have "f a = 0 \<or> (\<exists>a\<in>A. f a = 0)" by simp |
1137 then have "f a * setprod f A = 0" by rule (simp_all add: insert) |
1137 then have "f a * prod f A = 0" by rule (simp_all add: insert) |
1138 with insert show ?case by simp |
1138 with insert show ?case by simp |
1139 qed |
1139 qed |
1140 |
1140 |
1141 lemma setprod_dvd_setprod_subset2: |
1141 lemma prod_dvd_prod_subset2: |
1142 assumes "finite B" and "A \<subseteq> B" and "\<And>a. a \<in> A \<Longrightarrow> f a dvd g a" |
1142 assumes "finite B" and "A \<subseteq> B" and "\<And>a. a \<in> A \<Longrightarrow> f a dvd g a" |
1143 shows "setprod f A dvd setprod g B" |
1143 shows "prod f A dvd prod g B" |
1144 proof - |
1144 proof - |
1145 from assms have "setprod f A dvd setprod g A" |
1145 from assms have "prod f A dvd prod g A" |
1146 by (auto intro: setprod_dvd_setprod) |
1146 by (auto intro: prod_dvd_prod) |
1147 moreover from assms have "setprod g A dvd setprod g B" |
1147 moreover from assms have "prod g A dvd prod g B" |
1148 by (auto intro: setprod_dvd_setprod_subset) |
1148 by (auto intro: prod_dvd_prod_subset) |
1149 ultimately show ?thesis by (rule dvd_trans) |
1149 ultimately show ?thesis by (rule dvd_trans) |
1150 qed |
1150 qed |
1151 |
1151 |
1152 end |
1152 end |
1153 |
1153 |
1154 lemma (in semidom) setprod_zero_iff [simp]: |
1154 lemma (in semidom) prod_zero_iff [simp]: |
1155 fixes f :: "'b \<Rightarrow> 'a" |
1155 fixes f :: "'b \<Rightarrow> 'a" |
1156 assumes "finite A" |
1156 assumes "finite A" |
1157 shows "setprod f A = 0 \<longleftrightarrow> (\<exists>a\<in>A. f a = 0)" |
1157 shows "prod f A = 0 \<longleftrightarrow> (\<exists>a\<in>A. f a = 0)" |
1158 using assms by (induct A) (auto simp: no_zero_divisors) |
1158 using assms by (induct A) (auto simp: no_zero_divisors) |
1159 |
1159 |
1160 lemma (in semidom_divide) setprod_diff1: |
1160 lemma (in semidom_divide) prod_diff1: |
1161 assumes "finite A" and "f a \<noteq> 0" |
1161 assumes "finite A" and "f a \<noteq> 0" |
1162 shows "setprod f (A - {a}) = (if a \<in> A then setprod f A div f a else setprod f A)" |
1162 shows "prod f (A - {a}) = (if a \<in> A then prod f A div f a else prod f A)" |
1163 proof (cases "a \<notin> A") |
1163 proof (cases "a \<notin> A") |
1164 case True |
1164 case True |
1165 then show ?thesis by simp |
1165 then show ?thesis by simp |
1166 next |
1166 next |
1167 case False |
1167 case False |
1194 lemma sum_zero_power' [simp]: |
1194 lemma sum_zero_power' [simp]: |
1195 "(\<Sum>i\<in>A. c i * 0^i / d i) = (if finite A \<and> 0 \<in> A then c 0 / d 0 else 0)" |
1195 "(\<Sum>i\<in>A. c i * 0^i / d i) = (if finite A \<and> 0 \<in> A then c 0 / d 0 else 0)" |
1196 for c :: "nat \<Rightarrow> 'a::field" |
1196 for c :: "nat \<Rightarrow> 'a::field" |
1197 using sum_zero_power [of "\<lambda>i. c i / d i" A] by auto |
1197 using sum_zero_power [of "\<lambda>i. c i / d i" A] by auto |
1198 |
1198 |
1199 lemma (in field) setprod_inversef: |
1199 lemma (in field) prod_inversef: |
1200 "finite A \<Longrightarrow> setprod (inverse \<circ> f) A = inverse (setprod f A)" |
1200 "finite A \<Longrightarrow> prod (inverse \<circ> f) A = inverse (prod f A)" |
1201 by (induct A rule: finite_induct) simp_all |
1201 by (induct A rule: finite_induct) simp_all |
1202 |
1202 |
1203 lemma (in field) setprod_dividef: "finite A \<Longrightarrow> (\<Prod>x\<in>A. f x / g x) = setprod f A / setprod g A" |
1203 lemma (in field) prod_dividef: "finite A \<Longrightarrow> (\<Prod>x\<in>A. f x / g x) = prod f A / prod g A" |
1204 using setprod_inversef [of A g] by (simp add: divide_inverse setprod.distrib) |
1204 using prod_inversef [of A g] by (simp add: divide_inverse prod.distrib) |
1205 |
1205 |
1206 lemma setprod_Un: |
1206 lemma prod_Un: |
1207 fixes f :: "'b \<Rightarrow> 'a :: field" |
1207 fixes f :: "'b \<Rightarrow> 'a :: field" |
1208 assumes "finite A" and "finite B" |
1208 assumes "finite A" and "finite B" |
1209 and "\<forall>x\<in>A \<inter> B. f x \<noteq> 0" |
1209 and "\<forall>x\<in>A \<inter> B. f x \<noteq> 0" |
1210 shows "setprod f (A \<union> B) = setprod f A * setprod f B / setprod f (A \<inter> B)" |
1210 shows "prod f (A \<union> B) = prod f A * prod f B / prod f (A \<inter> B)" |
1211 proof - |
1211 proof - |
1212 from assms have "setprod f A * setprod f B = setprod f (A \<union> B) * setprod f (A \<inter> B)" |
1212 from assms have "prod f A * prod f B = prod f (A \<union> B) * prod f (A \<inter> B)" |
1213 by (simp add: setprod.union_inter [symmetric, of A B]) |
1213 by (simp add: prod.union_inter [symmetric, of A B]) |
1214 with assms show ?thesis |
1214 with assms show ?thesis |
1215 by simp |
1215 by simp |
1216 qed |
1216 qed |
1217 |
1217 |
1218 lemma (in linordered_semidom) setprod_nonneg: "(\<forall>a\<in>A. 0 \<le> f a) \<Longrightarrow> 0 \<le> setprod f A" |
1218 lemma (in linordered_semidom) prod_nonneg: "(\<forall>a\<in>A. 0 \<le> f a) \<Longrightarrow> 0 \<le> prod f A" |
1219 by (induct A rule: infinite_finite_induct) simp_all |
1219 by (induct A rule: infinite_finite_induct) simp_all |
1220 |
1220 |
1221 lemma (in linordered_semidom) setprod_pos: "(\<forall>a\<in>A. 0 < f a) \<Longrightarrow> 0 < setprod f A" |
1221 lemma (in linordered_semidom) prod_pos: "(\<forall>a\<in>A. 0 < f a) \<Longrightarrow> 0 < prod f A" |
1222 by (induct A rule: infinite_finite_induct) simp_all |
1222 by (induct A rule: infinite_finite_induct) simp_all |
1223 |
1223 |
1224 lemma (in linordered_semidom) setprod_mono: |
1224 lemma (in linordered_semidom) prod_mono: |
1225 "\<forall>i\<in>A. 0 \<le> f i \<and> f i \<le> g i \<Longrightarrow> setprod f A \<le> setprod g A" |
1225 "\<forall>i\<in>A. 0 \<le> f i \<and> f i \<le> g i \<Longrightarrow> prod f A \<le> prod g A" |
1226 by (induct A rule: infinite_finite_induct) (auto intro!: setprod_nonneg mult_mono) |
1226 by (induct A rule: infinite_finite_induct) (auto intro!: prod_nonneg mult_mono) |
1227 |
1227 |
1228 lemma (in linordered_semidom) setprod_mono_strict: |
1228 lemma (in linordered_semidom) prod_mono_strict: |
1229 assumes "finite A" "\<forall>i\<in>A. 0 \<le> f i \<and> f i < g i" "A \<noteq> {}" |
1229 assumes "finite A" "\<forall>i\<in>A. 0 \<le> f i \<and> f i < g i" "A \<noteq> {}" |
1230 shows "setprod f A < setprod g A" |
1230 shows "prod f A < prod g A" |
1231 using assms |
1231 using assms |
1232 proof (induct A rule: finite_induct) |
1232 proof (induct A rule: finite_induct) |
1233 case empty |
1233 case empty |
1234 then show ?case by simp |
1234 then show ?case by simp |
1235 next |
1235 next |
1236 case insert |
1236 case insert |
1237 then show ?case by (force intro: mult_strict_mono' setprod_nonneg) |
1237 then show ?case by (force intro: mult_strict_mono' prod_nonneg) |
1238 qed |
1238 qed |
1239 |
1239 |
1240 lemma (in linordered_field) abs_setprod: "\<bar>setprod f A\<bar> = (\<Prod>x\<in>A. \<bar>f x\<bar>)" |
1240 lemma (in linordered_field) abs_prod: "\<bar>prod f A\<bar> = (\<Prod>x\<in>A. \<bar>f x\<bar>)" |
1241 by (induct A rule: infinite_finite_induct) (simp_all add: abs_mult) |
1241 by (induct A rule: infinite_finite_induct) (simp_all add: abs_mult) |
1242 |
1242 |
1243 lemma setprod_eq_1_iff [simp]: "finite A \<Longrightarrow> setprod f A = 1 \<longleftrightarrow> (\<forall>a\<in>A. f a = 1)" |
1243 lemma prod_eq_1_iff [simp]: "finite A \<Longrightarrow> prod f A = 1 \<longleftrightarrow> (\<forall>a\<in>A. f a = 1)" |
1244 for f :: "'a \<Rightarrow> nat" |
1244 for f :: "'a \<Rightarrow> nat" |
1245 by (induct A rule: finite_induct) simp_all |
1245 by (induct A rule: finite_induct) simp_all |
1246 |
1246 |
1247 lemma setprod_pos_nat_iff [simp]: "finite A \<Longrightarrow> setprod f A > 0 \<longleftrightarrow> (\<forall>a\<in>A. f a > 0)" |
1247 lemma prod_pos_nat_iff [simp]: "finite A \<Longrightarrow> prod f A > 0 \<longleftrightarrow> (\<forall>a\<in>A. f a > 0)" |
1248 for f :: "'a \<Rightarrow> nat" |
1248 for f :: "'a \<Rightarrow> nat" |
1249 using setprod_zero_iff by (simp del: neq0_conv add: zero_less_iff_neq_zero) |
1249 using prod_zero_iff by (simp del: neq0_conv add: zero_less_iff_neq_zero) |
1250 |
1250 |
1251 lemma setprod_constant: "(\<Prod>x\<in> A. y) = y ^ card A" |
1251 lemma prod_constant: "(\<Prod>x\<in> A. y) = y ^ card A" |
1252 for y :: "'a::comm_monoid_mult" |
1252 for y :: "'a::comm_monoid_mult" |
1253 by (induct A rule: infinite_finite_induct) simp_all |
1253 by (induct A rule: infinite_finite_induct) simp_all |
1254 |
1254 |
1255 lemma setprod_power_distrib: "setprod f A ^ n = setprod (\<lambda>x. (f x) ^ n) A" |
1255 lemma prod_power_distrib: "prod f A ^ n = prod (\<lambda>x. (f x) ^ n) A" |
1256 for f :: "'a \<Rightarrow> 'b::comm_semiring_1" |
1256 for f :: "'a \<Rightarrow> 'b::comm_semiring_1" |
1257 by (induct A rule: infinite_finite_induct) (auto simp add: power_mult_distrib) |
1257 by (induct A rule: infinite_finite_induct) (auto simp add: power_mult_distrib) |
1258 |
1258 |
1259 lemma power_sum: "c ^ (\<Sum>a\<in>A. f a) = (\<Prod>a\<in>A. c ^ f a)" |
1259 lemma power_sum: "c ^ (\<Sum>a\<in>A. f a) = (\<Prod>a\<in>A. c ^ f a)" |
1260 by (induct A rule: infinite_finite_induct) (simp_all add: power_add) |
1260 by (induct A rule: infinite_finite_induct) (simp_all add: power_add) |
1261 |
1261 |
1262 lemma setprod_gen_delta: |
1262 lemma prod_gen_delta: |
1263 fixes b :: "'b \<Rightarrow> 'a::comm_monoid_mult" |
1263 fixes b :: "'b \<Rightarrow> 'a::comm_monoid_mult" |
1264 assumes fin: "finite S" |
1264 assumes fin: "finite S" |
1265 shows "setprod (\<lambda>k. if k = a then b k else c) S = |
1265 shows "prod (\<lambda>k. if k = a then b k else c) S = |
1266 (if a \<in> S then b a * c ^ (card S - 1) else c ^ card S)" |
1266 (if a \<in> S then b a * c ^ (card S - 1) else c ^ card S)" |
1267 proof - |
1267 proof - |
1268 let ?f = "(\<lambda>k. if k=a then b k else c)" |
1268 let ?f = "(\<lambda>k. if k=a then b k else c)" |
1269 show ?thesis |
1269 show ?thesis |
1270 proof (cases "a \<in> S") |
1270 proof (cases "a \<in> S") |
1271 case False |
1271 case False |
1272 then have "\<forall> k\<in> S. ?f k = c" by simp |
1272 then have "\<forall> k\<in> S. ?f k = c" by simp |
1273 with False show ?thesis by (simp add: setprod_constant) |
1273 with False show ?thesis by (simp add: prod_constant) |
1274 next |
1274 next |
1275 case True |
1275 case True |
1276 let ?A = "S - {a}" |
1276 let ?A = "S - {a}" |
1277 let ?B = "{a}" |
1277 let ?B = "{a}" |
1278 from True have eq: "S = ?A \<union> ?B" by blast |
1278 from True have eq: "S = ?A \<union> ?B" by blast |
1279 have disjoint: "?A \<inter> ?B = {}" by simp |
1279 have disjoint: "?A \<inter> ?B = {}" by simp |
1280 from fin have fin': "finite ?A" "finite ?B" by auto |
1280 from fin have fin': "finite ?A" "finite ?B" by auto |
1281 have f_A0: "setprod ?f ?A = setprod (\<lambda>i. c) ?A" |
1281 have f_A0: "prod ?f ?A = prod (\<lambda>i. c) ?A" |
1282 by (rule setprod.cong) auto |
1282 by (rule prod.cong) auto |
1283 from fin True have card_A: "card ?A = card S - 1" by auto |
1283 from fin True have card_A: "card ?A = card S - 1" by auto |
1284 have f_A1: "setprod ?f ?A = c ^ card ?A" |
1284 have f_A1: "prod ?f ?A = c ^ card ?A" |
1285 unfolding f_A0 by (rule setprod_constant) |
1285 unfolding f_A0 by (rule prod_constant) |
1286 have "setprod ?f ?A * setprod ?f ?B = setprod ?f S" |
1286 have "prod ?f ?A * prod ?f ?B = prod ?f S" |
1287 using setprod.union_disjoint[OF fin' disjoint, of ?f, unfolded eq[symmetric]] |
1287 using prod.union_disjoint[OF fin' disjoint, of ?f, unfolded eq[symmetric]] |
1288 by simp |
1288 by simp |
1289 with True card_A show ?thesis |
1289 with True card_A show ?thesis |
1290 by (simp add: f_A1 field_simps cong add: setprod.cong cong del: if_weak_cong) |
1290 by (simp add: f_A1 field_simps cong add: prod.cong cong del: if_weak_cong) |
1291 qed |
1291 qed |
1292 qed |
1292 qed |
1293 |
1293 |
1294 lemma sum_image_le: |
1294 lemma sum_image_le: |
1295 fixes g :: "'a \<Rightarrow> 'b::ordered_ab_group_add" |
1295 fixes g :: "'a \<Rightarrow> 'b::ordered_ab_group_add" |