Theory Univariate_Roots_Bound
section ‹Roots Bound for Univariate Polynomials›
theory Univariate_Roots_Bound
imports
"HOL-Computational_Algebra.Polynomial"
begin
text ‹
\textbf{NOTE:} if considered to be useful enough, the lemmas in this theory could be moved to
the theory @{theory "HOL-Computational_Algebra.Polynomial"}.
›
subsection ‹Basic lemmas›
lemma finite_non_zero_coeffs: ‹finite {n. poly.coeff p n ≠ 0}›
using MOST_coeff_eq_0 eventually_cofinite
by fastforce
text ‹Univariate degree in terms of @{term Max}›
lemma poly_degree_eq_Max_non_zero_coeffs:
"degree p = Max (insert 0 {n. poly.coeff p n ≠ 0})"
by (intro le_antisym degree_le) (auto simp add: finite_non_zero_coeffs le_degree)
subsection ‹Univariate roots bound›
text ‹The number of roots of a product of polynomials is bounded by
the sum of the number of roots of each.›
lemma card_poly_mult_roots:
fixes p :: "'a::{comm_ring_1,ring_no_zero_divisors} poly"
and q :: "'a::{comm_ring_1,ring_no_zero_divisors} poly"
assumes "p ≠ 0" and "q ≠ 0"
shows "card {x. poly p x * poly q x = 0} ≤ card {x. poly p x = 0} + card {x. poly q x = 0}"
proof -
have "card {x . poly p x * poly q x = 0} ≤ card ({x . poly p x = 0} ∪ {x . poly q x = 0})"
by (auto simp add: poly_roots_finite assms intro!: card_mono)
also have "… ≤ card {x . poly p x = 0} + card {x . poly q x = 0}"
by(auto simp add: Finite_Set.card_Un_le)
finally show ?thesis .
qed
text ‹A univariate polynomial p has at most deg p roots.›
lemma univariate_roots_bound:
fixes p :: ‹'a::idom poly›
assumes ‹p ≠ 0›
shows ‹card {x. poly p x = 0} ≤ degree p›
using assms
proof (induction "degree p" arbitrary: p rule: nat_less_induct)
case 1
then show ?case
proof(cases "∃r. poly p r = 0")
case True
then obtain r where "poly p r = 0" by(auto)
let ?xr = "[:- r, 1:] ^ order r p"
obtain q where "p = ?xr * q" using order_decomp ‹p ≠ 0› by(auto)
have "q ≠ 0" using ‹p = ?xr * q› ‹p ≠ 0› by(auto)
have "?xr ≠ 0" by(simp)
have "degree ?xr > 0" using ‹?xr ≠ 0› ‹p ≠ 0› ‹poly p r = 0›
by (simp add: degree_power_eq order_root)
have "degree q < degree p"
using ‹?xr ≠ 0› ‹q ≠ 0› ‹p = ?xr * q› ‹degree ?xr > 0›
degree_mult_eq[where p = "?xr" and q = "q"]
by (simp)
have x_roots: "card {r. poly ?xr r = 0} = 1" using ‹p ≠ 0› ‹poly p r = 0›
by(simp add: order_root)
have q_roots: "card {r. poly q r = 0} ≤ degree q" using ‹q ≠ 0› ‹degree q < degree p› 1
by (simp)
have "card {r . poly p r = 0} ≤ degree p"
using ‹p = ?xr * q› ‹q ≠ 0› ‹?xr ≠ 0› ‹degree q < degree p›
poly_mult[where p = "?xr" and q = "q"]
card_poly_mult_roots[where p = "?xr" and q = "q"]
x_roots q_roots
by (simp)
then show ?thesis .
next
case False
then show ?thesis by simp
qed
qed
end