src/HOL/Library/Polynomial_Factorial.thy
changeset 64795 8e7db8df16a0
parent 64794 6f7391f28197
child 64848 c50db2128048
equal deleted inserted replaced
64794:6f7391f28197 64795:8e7db8df16a0
    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