16 |
16 |
17 subsection \<open>Various facts about polynomials\<close> |
17 subsection \<open>Various facts about polynomials\<close> |
18 |
18 |
19 lemma prod_mset_const_poly: "prod_mset (image_mset (\<lambda>x. [:f x:]) A) = [:prod_mset (image_mset f A):]" |
19 lemma prod_mset_const_poly: "prod_mset (image_mset (\<lambda>x. [:f x:]) A) = [:prod_mset (image_mset f A):]" |
20 by (induction A) (simp_all add: one_poly_def mult_ac) |
20 by (induction A) (simp_all add: one_poly_def mult_ac) |
21 |
|
22 lemma is_unit_smult_iff: "smult c p dvd 1 \<longleftrightarrow> c dvd 1 \<and> p dvd 1" |
|
23 proof - |
|
24 have "smult c p = [:c:] * p" by simp |
|
25 also have "\<dots> dvd 1 \<longleftrightarrow> c dvd 1 \<and> p dvd 1" |
|
26 proof safe |
|
27 assume A: "[:c:] * p dvd 1" |
|
28 thus "p dvd 1" by (rule dvd_mult_right) |
|
29 from A obtain q where B: "1 = [:c:] * p * q" by (erule dvdE) |
|
30 have "c dvd c * (coeff p 0 * coeff q 0)" by simp |
|
31 also have "\<dots> = coeff ([:c:] * p * q) 0" by (simp add: mult.assoc coeff_mult) |
|
32 also note B [symmetric] |
|
33 finally show "c dvd 1" by simp |
|
34 next |
|
35 assume "c dvd 1" "p dvd 1" |
|
36 from \<open>c dvd 1\<close> obtain d where "1 = c * d" by (erule dvdE) |
|
37 hence "1 = [:c:] * [:d:]" by (simp add: one_poly_def mult_ac) |
|
38 hence "[:c:] dvd 1" by (rule dvdI) |
|
39 from mult_dvd_mono[OF this \<open>p dvd 1\<close>] show "[:c:] * p dvd 1" by simp |
|
40 qed |
|
41 finally show ?thesis . |
|
42 qed |
|
43 |
|
44 lemma degree_mod_less': "b \<noteq> 0 \<Longrightarrow> a mod b \<noteq> 0 \<Longrightarrow> degree (a mod b) < degree b" |
|
45 using degree_mod_less[of b a] by auto |
|
46 |
|
47 lemma smult_eq_iff: |
|
48 assumes "(b :: 'a :: field) \<noteq> 0" |
|
49 shows "smult a p = smult b q \<longleftrightarrow> smult (a / b) p = q" |
|
50 proof |
|
51 assume "smult a p = smult b q" |
|
52 also from assms have "smult (inverse b) \<dots> = q" by simp |
|
53 finally show "smult (a / b) p = q" by (simp add: field_simps) |
|
54 qed (insert assms, auto) |
|
55 |
21 |
56 lemma irreducible_const_poly_iff: |
22 lemma irreducible_const_poly_iff: |
57 fixes c :: "'a :: {comm_semiring_1,semiring_no_zero_divisors}" |
23 fixes c :: "'a :: {comm_semiring_1,semiring_no_zero_divisors}" |
58 shows "irreducible [:c:] \<longleftrightarrow> irreducible c" |
24 shows "irreducible [:c:] \<longleftrightarrow> irreducible c" |
59 proof |
25 proof |
156 by (subst (2) normalize_mult_unit_factor [symmetric, of x]) |
122 by (subst (2) normalize_mult_unit_factor [symmetric, of x]) |
157 (simp del: normalize_mult_unit_factor) |
123 (simp del: normalize_mult_unit_factor) |
158 |
124 |
159 lemma normalize_snd_quot_of_fract: "normalize (snd (quot_of_fract x)) = snd (quot_of_fract x)" |
125 lemma normalize_snd_quot_of_fract: "normalize (snd (quot_of_fract x)) = snd (quot_of_fract x)" |
160 by (intro unit_factor_1_imp_normalized unit_factor_snd_quot_of_fract) |
126 by (intro unit_factor_1_imp_normalized unit_factor_snd_quot_of_fract) |
161 |
|
162 |
|
163 subsection \<open>Content and primitive part of a polynomial\<close> |
|
164 |
|
165 definition content :: "('a :: semiring_Gcd poly) \<Rightarrow> 'a" where |
|
166 "content p = Gcd (set (coeffs p))" |
|
167 |
|
168 lemma content_0 [simp]: "content 0 = 0" |
|
169 by (simp add: content_def) |
|
170 |
|
171 lemma content_1 [simp]: "content 1 = 1" |
|
172 by (simp add: content_def) |
|
173 |
|
174 lemma content_const [simp]: "content [:c:] = normalize c" |
|
175 by (simp add: content_def cCons_def) |
|
176 |
|
177 lemma const_poly_dvd_iff_dvd_content: |
|
178 fixes c :: "'a :: semiring_Gcd" |
|
179 shows "[:c:] dvd p \<longleftrightarrow> c dvd content p" |
|
180 proof (cases "p = 0") |
|
181 case [simp]: False |
|
182 have "[:c:] dvd p \<longleftrightarrow> (\<forall>n. c dvd coeff p n)" by (rule const_poly_dvd_iff) |
|
183 also have "\<dots> \<longleftrightarrow> (\<forall>a\<in>set (coeffs p). c dvd a)" |
|
184 proof safe |
|
185 fix n :: nat assume "\<forall>a\<in>set (coeffs p). c dvd a" |
|
186 thus "c dvd coeff p n" |
|
187 by (cases "n \<le> degree p") (auto simp: coeff_eq_0 coeffs_def split: if_splits) |
|
188 qed (auto simp: coeffs_def simp del: upt_Suc split: if_splits) |
|
189 also have "\<dots> \<longleftrightarrow> c dvd content p" |
|
190 by (simp add: content_def dvd_Gcd_iff mult.commute [of "unit_factor x" for x] |
|
191 dvd_mult_unit_iff) |
|
192 finally show ?thesis . |
|
193 qed simp_all |
|
194 |
|
195 lemma content_dvd [simp]: "[:content p:] dvd p" |
|
196 by (subst const_poly_dvd_iff_dvd_content) simp_all |
|
197 |
|
198 lemma content_dvd_coeff [simp]: "content p dvd coeff p n" |
|
199 by (cases "n \<le> degree p") |
|
200 (auto simp: content_def coeffs_def not_le coeff_eq_0 simp del: upt_Suc intro: Gcd_dvd) |
|
201 |
|
202 lemma content_dvd_coeffs: "c \<in> set (coeffs p) \<Longrightarrow> content p dvd c" |
|
203 by (simp add: content_def Gcd_dvd) |
|
204 |
|
205 lemma normalize_content [simp]: "normalize (content p) = content p" |
|
206 by (simp add: content_def) |
|
207 |
|
208 lemma is_unit_content_iff [simp]: "is_unit (content p) \<longleftrightarrow> content p = 1" |
|
209 proof |
|
210 assume "is_unit (content p)" |
|
211 hence "normalize (content p) = 1" by (simp add: is_unit_normalize del: normalize_content) |
|
212 thus "content p = 1" by simp |
|
213 qed auto |
|
214 |
|
215 lemma content_smult [simp]: "content (smult c p) = normalize c * content p" |
|
216 by (simp add: content_def coeffs_smult Gcd_mult) |
|
217 |
|
218 lemma content_eq_zero_iff [simp]: "content p = 0 \<longleftrightarrow> p = 0" |
|
219 by (auto simp: content_def simp: poly_eq_iff coeffs_def) |
|
220 |
|
221 definition primitive_part :: "'a :: {semiring_Gcd,idom_divide} poly \<Rightarrow> 'a poly" where |
|
222 "primitive_part p = (if p = 0 then 0 else map_poly (\<lambda>x. x div content p) p)" |
|
223 |
|
224 lemma primitive_part_0 [simp]: "primitive_part 0 = 0" |
|
225 by (simp add: primitive_part_def) |
|
226 |
|
227 lemma content_times_primitive_part [simp]: |
|
228 fixes p :: "'a :: {idom_divide, semiring_Gcd} poly" |
|
229 shows "smult (content p) (primitive_part p) = p" |
|
230 proof (cases "p = 0") |
|
231 case False |
|
232 thus ?thesis |
|
233 unfolding primitive_part_def |
|
234 by (auto simp: smult_conv_map_poly map_poly_map_poly o_def content_dvd_coeffs |
|
235 intro: map_poly_idI) |
|
236 qed simp_all |
|
237 |
|
238 lemma primitive_part_eq_0_iff [simp]: "primitive_part p = 0 \<longleftrightarrow> p = 0" |
|
239 proof (cases "p = 0") |
|
240 case False |
|
241 hence "primitive_part p = map_poly (\<lambda>x. x div content p) p" |
|
242 by (simp add: primitive_part_def) |
|
243 also from False have "\<dots> = 0 \<longleftrightarrow> p = 0" |
|
244 by (intro map_poly_eq_0_iff) (auto simp: dvd_div_eq_0_iff content_dvd_coeffs) |
|
245 finally show ?thesis using False by simp |
|
246 qed simp |
|
247 |
|
248 lemma content_primitive_part [simp]: |
|
249 assumes "p \<noteq> 0" |
|
250 shows "content (primitive_part p) = 1" |
|
251 proof - |
|
252 have "p = smult (content p) (primitive_part p)" by simp |
|
253 also have "content \<dots> = content p * content (primitive_part p)" |
|
254 by (simp del: content_times_primitive_part) |
|
255 finally show ?thesis using assms by simp |
|
256 qed |
|
257 |
|
258 lemma content_decompose: |
|
259 fixes p :: "'a :: semiring_Gcd poly" |
|
260 obtains p' where "p = smult (content p) p'" "content p' = 1" |
|
261 proof (cases "p = 0") |
|
262 case True |
|
263 thus ?thesis by (intro that[of 1]) simp_all |
|
264 next |
|
265 case False |
|
266 from content_dvd[of p] obtain r where r: "p = [:content p:] * r" by (erule dvdE) |
|
267 have "content p * 1 = content p * content r" by (subst r) simp |
|
268 with False have "content r = 1" by (subst (asm) mult_left_cancel) simp_all |
|
269 with r show ?thesis by (intro that[of r]) simp_all |
|
270 qed |
|
271 |
|
272 lemma smult_content_normalize_primitive_part [simp]: |
|
273 "smult (content p) (normalize (primitive_part p)) = normalize p" |
|
274 proof - |
|
275 have "smult (content p) (normalize (primitive_part p)) = |
|
276 normalize ([:content p:] * primitive_part p)" |
|
277 by (subst normalize_mult) (simp_all add: normalize_const_poly) |
|
278 also have "[:content p:] * primitive_part p = p" by simp |
|
279 finally show ?thesis . |
|
280 qed |
|
281 |
|
282 lemma content_dvd_contentI [intro]: |
|
283 "p dvd q \<Longrightarrow> content p dvd content q" |
|
284 using const_poly_dvd_iff_dvd_content content_dvd dvd_trans by blast |
|
285 |
|
286 lemma primitive_part_const_poly [simp]: "primitive_part [:x:] = [:unit_factor x:]" |
|
287 by (simp add: primitive_part_def map_poly_pCons) |
|
288 |
|
289 lemma primitive_part_prim: "content p = 1 \<Longrightarrow> primitive_part p = p" |
|
290 by (auto simp: primitive_part_def) |
|
291 |
|
292 lemma degree_primitive_part [simp]: "degree (primitive_part p) = degree p" |
|
293 proof (cases "p = 0") |
|
294 case False |
|
295 have "p = smult (content p) (primitive_part p)" by simp |
|
296 also from False have "degree \<dots> = degree (primitive_part p)" |
|
297 by (subst degree_smult_eq) simp_all |
|
298 finally show ?thesis .. |
|
299 qed simp_all |
|
300 |
127 |
301 |
128 |
302 subsection \<open>Lifting polynomial coefficients to the field of fractions\<close> |
129 subsection \<open>Lifting polynomial coefficients to the field of fractions\<close> |
303 |
130 |
304 abbreviation (input) fract_poly |
131 abbreviation (input) fract_poly |