src/HOL/Computational_Algebra/Fundamental_Theorem_Algebra.thy
changeset 80061 4c1347e172b1
parent 77341 127a51771f34
--- a/src/HOL/Computational_Algebra/Fundamental_Theorem_Algebra.thy	Sat Mar 30 01:12:48 2024 +0100
+++ b/src/HOL/Computational_Algebra/Fundamental_Theorem_Algebra.thy	Fri Mar 29 19:28:59 2024 +0100
@@ -518,7 +518,7 @@
 
 text \<open>Fundamental theorem of algebra\<close>
 
-lemma fundamental_theorem_of_algebra:
+theorem fundamental_theorem_of_algebra:
   assumes nc: "\<not> constant (poly p)"
   shows "\<exists>z::complex. poly p z = 0"
   using nc
@@ -779,6 +779,92 @@
     by (metis degree_eq_zeroE pcompose_const poly_0 poly_pcompose that)
 qed
 
+lemma complex_poly_decompose:
+  "smult (lead_coeff p) (\<Prod>z|poly p z = 0. [:-z, 1:] ^ order z p) = (p :: complex poly)"
+proof (induction p rule: poly_root_order_induct)
+  case (no_roots p)
+  show ?case
+  proof (cases "degree p = 0")
+    case False
+    hence "\<not>constant (poly p)" by (subst constant_degree)
+    with fundamental_theorem_of_algebra and no_roots show ?thesis by blast
+  qed (auto elim!: degree_eq_zeroE)
+next
+  case (root p x n)
+  from root have *: "{z. poly ([:- x, 1:] ^ n * p) z = 0} = insert x {z. poly p z = 0}"
+    by auto
+  have "smult (lead_coeff ([:-x, 1:] ^ n * p)) 
+           (\<Prod>z|poly ([:-x,1:] ^ n * p) z = 0. [:-z, 1:] ^ order z ([:- x, 1:] ^ n * p)) = 
+        [:- x, 1:] ^ order x ([:- x, 1:] ^ n * p) * 
+          smult (lead_coeff p) (\<Prod>z\<in>{z. poly p z = 0}. [:- z, 1:] ^ order z ([:- x, 1:] ^ n * p))"
+    by (subst *, subst prod.insert) 
+       (insert root, auto intro: poly_roots_finite simp: mult_ac lead_coeff_mult lead_coeff_power)
+  also have "order x ([:- x, 1:] ^ n * p) = n"
+    using root by (subst order_mult) (auto simp: order_power_n_n order_0I)
+  also have "(\<Prod>z\<in>{z. poly p z = 0}. [:- z, 1:] ^ order z ([:- x, 1:] ^ n * p)) =
+               (\<Prod>z\<in>{z. poly p z = 0}. [:- z, 1:] ^ order z p)"
+  proof (intro prod.cong refl, goal_cases)
+    case (1 y)
+    with root have "order y ([:-x,1:] ^ n) = 0" by (intro order_0I) auto 
+    thus ?case using root by (subst order_mult) auto
+  qed
+  also note root.IH
+  finally show ?case .
+qed simp_all
+
+instance complex :: alg_closed_field
+  by standard (use fundamental_theorem_of_algebra constant_degree neq0_conv in blast)
+
+lemma size_proots_complex: "size (proots (p :: complex poly)) = degree p"
+proof (cases "p = 0")
+  case [simp]: False
+  show "size (proots p) = degree p"
+    by (subst (1 2) complex_poly_decompose [symmetric])
+       (simp add: proots_prod proots_power degree_prod_sum_eq degree_power_eq)
+qed auto
+
+lemma complex_poly_decompose_multiset:
+  "smult (lead_coeff p) (\<Prod>x\<in>#proots p. [:-x, 1:]) = (p :: complex poly)"
+proof (cases "p = 0")
+  case False
+  hence "(\<Prod>x\<in>#proots p. [:-x, 1:]) = (\<Prod>x | poly p x = 0. [:-x, 1:] ^ order x p)"
+    by (subst image_prod_mset_multiplicity) simp_all
+  also have "smult (lead_coeff p) \<dots> = p"
+    by (rule complex_poly_decompose)
+  finally show ?thesis .
+qed auto
+
+lemma complex_poly_decompose':
+  obtains root where "smult (lead_coeff p) (\<Prod>i<degree p. [:-root i, 1:]) = (p :: complex poly)"
+proof -
+  obtain roots where roots: "mset roots = proots p"
+    using ex_mset by blast
+
+  have "p = smult (lead_coeff p) (\<Prod>x\<in>#proots p. [:-x, 1:])"
+    by (rule complex_poly_decompose_multiset [symmetric])
+  also have "(\<Prod>x\<in>#proots p. [:-x, 1:]) = (\<Prod>x\<leftarrow>roots. [:-x, 1:])"
+    by (subst prod_mset_prod_list [symmetric]) (simp add: roots)
+  also have "\<dots> = (\<Prod>i<length roots. [:-roots ! i, 1:])"
+    by (subst prod.list_conv_set_nth) (auto simp: atLeast0LessThan)
+  finally have eq: "p = smult (lead_coeff p) (\<Prod>i<length roots. [:-roots ! i, 1:])" .
+  also have [simp]: "degree p = length roots"
+    using roots by (subst eq) (auto simp: degree_prod_sum_eq)
+  finally show ?thesis by (intro that[of "\<lambda>i. roots ! i"]) auto
+qed
+
+lemma complex_poly_decompose_rsquarefree:
+  assumes "rsquarefree p"
+  shows   "smult (lead_coeff p) (\<Prod>z|poly p z = 0. [:-z, 1:]) = (p :: complex poly)"
+proof (cases "p = 0")
+  case False
+  have "(\<Prod>z|poly p z = 0. [:-z, 1:]) = (\<Prod>z|poly p z = 0. [:-z, 1:] ^ order z p)"
+    using assms False by (intro prod.cong) (auto simp: rsquarefree_root_order)
+  also have "smult (lead_coeff p) \<dots> = p"
+    by (rule complex_poly_decompose)
+  finally show ?thesis .
+qed auto
+
+
 text \<open>Arithmetic operations on multivariate polynomials.\<close>
 
 lemma mpoly_base_conv: