Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  BF_Misc.thy

  Sprache: Isabelle
 

(*
    Author:     Wenda Li <wl302@cam.ac.uk / liwenda1990@hotmail.com>
*)


section "Misc results for polynomials and sign variations"

theory BF_Misc imports
  "HOL-Computational_Algebra.Polynomial_Factorial"
  "HOL-Computational_Algebra.Fundamental_Theorem_Algebra"
  Sturm_Tarski.Sturm_Tarski
begin

subsection Induction on polynomial roots

(*adapted from the poly_root_induct in Polynomial.thy.*)
lemma poly_root_induct_alt [case_names 0 no_proots root]:
  fixes p :: "'a :: idom poly"
  assumes "Q 0"
  assumes "p. (a. poly p a 0) ==> Q p"
  assumes "a p. Q p ==> Q ([:-a, 1:] * p)"
  shows   "Q p"
proof (induction "degree p" arbitrary: p rule: less_induct)
  case (less p)
  have ?case when "p=0" using Q 0 that by auto
  moreover have ?case when "a. poly p a = 0"
    using assms(2) that by blast
  moreover have ?case when "a. poly p a = 0" "p0"
  proof -
    obtain a where "poly p a =0" using a. poly p a = 0 by auto
    then obtain q where pq:"p= [:-a,1:] * q" by (meson dvdE poly_eq_0_iff_dvd)
    then have "q0" using p0 by auto
    then have "degree q<degree p" unfolding pq by (subst degree_mult_eq,auto)
    then have "Q q" using less by auto
    then show ?case using assms(3unfolding pq by auto
  qed
  ultimately show ?case by auto
qed

subsection Misc

lemma lead_coeff_pderiv:
  fixes p :: "'a::{comm_semiring_1,semiring_no_zero_divisors,semiring_char_0} poly"
  shows "lead_coeff (pderiv p) = of_nat (degree p) * lead_coeff p"
  apply (auto simp:degree_pderiv coeff_pderiv)
  apply (cases "degree p")
  by (auto simp add: coeff_eq_0)

lemma gcd_degree_le_min:
  assumes "p0" "q0"
  shows "degree (gcd p q) min (degree p) (degree q)"
  by (simp add: assms(1) assms(2) dvd_imp_degree_le)

lemma lead_coeff_normalize_field:
  fixes p::"'a::{field,semidom_divide_unit_factor} poly"
  assumes "p0"
  shows "lead_coeff (normalize p) = 1"
  by (metis (no_types, lifting) assms coeff_normalize divide_self_if dvd_field_iff 
      is_unit_unit_factor leading_coeff_0_iff normalize_eq_0_iff normalize_idem)

lemma smult_normalize_field_eq:
  fixes p::"'a::{field,semidom_divide_unit_factor} poly"
  shows "p = smult (lead_coeff p) (normalize p)"
proof (rule poly_eqI)
  fix n
  have "unit_factor (lead_coeff p) = lead_coeff p"
    by (metis dvd_field_iff is_unit_unit_factor unit_factor_0)
  then show "coeff p n = coeff (smult (lead_coeff p) (normalize p)) n"
    by simp
qed

lemma lead_coeff_gcd_field:
  fixes p q::"'a::field_gcd poly"
  assumes "p0 q0"
  shows "lead_coeff (gcd p q) = 1"
  using assms by (metis gcd.normalize_idem gcd_eq_0_iff lead_coeff_normalize_field)

lemma poly_gcd_0_iff:
  "poly (gcd p q) x = 0 poly p x=0 poly q x=0"
  by (simp add:poly_eq_0_iff_dvd)

lemma degree_eq_oneE:
  fixes p :: "'a::zero poly"
  assumes "degree p = 1"
  obtains a b where "p = [:a,b:]" "b0"
proof -
  obtain a b q where p:"p=pCons a (pCons b q)"
    by (metis pCons_cases)
  with assms have "q=0" by (cases "q = 0") simp_all
  with p have "p=[:a,b:]" by auto
  moreover then have "b0" using assms by auto
  ultimately show ?thesis ..
qed

subsection More results about sign variations (i.e. @{term changes}

lemma changes_0[simp]:"changes (0#xs) = changes xs"
  by (cases xs) auto

lemma changes_Cons:"changes (x#xs) = (if filter (λx. x0) xs = [] then
                            0
                          else if x* hd (filter (λx. x0) xs) < 0 then
                            1 + changes xs
                          else changes xs)"
  apply (induct xs)
  by auto

lemma changes_filter_eq:
  "changes (filter (λx. x0) xs) = changes xs"
  apply (induct xs)
  by (auto simp add:changes_Cons)

lemma changes_filter_empty:
  assumes "filter (λx. x0) xs = []"
  shows "changes xs = 0" "changes (a#xs) = 0" using assms
  apply (induct xs)
  apply auto
  by (metis changes_0 neq_Nil_conv)

lemma changes_append:
  assumes "xs [] ys [] (last xs = hd ys last xs0)"
  shows "changes (xs@ys) = changes xs + changes ys"
  using assms
proof (induct xs)
  case Nil
  then show ?case by simp
next
  case (Cons a xs)
  have ?case when "xs=[]"
    using that Cons 
    apply (cases ys)
    by auto
  moreover have ?case when "ys=[]"
    using that Cons by auto
  moreover have ?case when "xs[]" "ys[]"
  proof -
    have "filter (λx. x 0) xs []"
      using that Cons 
      apply auto 
      by (metis (mono_tags, lifting) filter.simps(1) filter.simps(2) filter_append snoc_eq_iff_butlast)
    then have "changes (a # xs @ ys) = changes (a # xs) + changes ys"
      apply (subst (1 2) changes_Cons)
      using that Cons by auto
    then show ?thesis by auto
  qed
  ultimately show ?case by blast
qed

lemma changes_drop_dup:
  assumes "xs []" "ys [] last xs=hd ys"
  shows "changes (xs@ys) = changes (xs@ tl ys)"
  using assms
proof (induct xs)
  case Nil
  then show ?case by simp
next
  case (Cons a xs)
  have ?case when "ys=[]"
    using that by simp
  moreover have ?case when "ys[]" "xs=[]"
    using that Cons
    apply auto
    by (metis changes.simps(3) list.exhaust_sel not_square_less_zero)
  moreover have ?case when "ys[]" "xs[]"
  proof -
    define ts ts' where "ts = filter (λx. x 0) (xs @ ys)"
      and "ts' = filter (λx. x 0) (xs @ tl ys)"
    have "(ts = [] ts' = []) hd ts = hd ts'"
    proof (cases "filter (λx. x 0) xs = []")
      case True
      then have "last xs = 0" using xs[]
        by (metis (mono_tags, lifting) append_butlast_last_id append_is_Nil_conv 
            filter.simps(2) filter_append list.simps(3))
      then have "hd ys=0" using Cons(3)[rule_format, OF ys[]xs[] by auto
      then have "filter (λx. x 0) ys = filter (λx. x 0) (tl ys)"
        by (metis (mono_tags, lifting) filter.simps(2) list.exhaust_sel that(1))
      then show ?thesis unfolding ts_def ts'_def by auto
    next
      case False
      then show ?thesis unfolding ts_def ts'_def by auto
    qed
    moreover have "changes (xs @ ys) = changes (xs @ tl ys)"
      apply (rule Cons(1))
      using that Cons(3by auto
    moreover have "changes (a # xs @ ys) = (if ts = [] then 0 else if a * hd ts < 0
            then 1 + changes (xs @ ys) else changes (xs @ ys))"
      using changes_Cons[of a "xs @ ys",folded ts_def] .
    moreover have "changes (a # xs @ tl ys) = (if ts' = [] then 0 else if a * hd ts' < 0
            then 1 + changes (xs @ tl ys) else changes (xs @ tl ys))"
      using changes_Cons[of a "xs @ tl ys",folded ts'_def] .
    ultimately show ?thesis by auto
  qed
  ultimately show ?case by blast
qed

(*
  TODO: the following lemmas contain duplicates of some lemmas in 
          Winding_Number_Eval/Missing_Algebraic.thy
  Will resolve later.  
*)


lemma Im_poly_of_real:
  "Im (poly p (of_real x)) = poly (map_poly Im p) x"
  apply (induct p)
  by (auto simp add:map_poly_pCons)
 
lemma Re_poly_of_real:
  "Re (poly p (of_real x)) = poly (map_poly Re p) x"
  apply (induct p)
  by (auto simp add:map_poly_pCons)

subsection More about @{term map_poly} and @{term of_real}

lemma of_real_poly_map_pCons[simp]:"map_poly of_real (pCons a p) = pCons (of_real a) (map_poly of_real p)" 
  by (simp add: map_poly_pCons)    
    
lemma of_real_poly_map_plus[simp]: "map_poly of_real (p + q) = map_poly of_real p + map_poly of_real q" 
  apply (rule poly_eqI)
  by (auto simp add: coeff_map_poly)  
 
lemma of_real_poly_map_smult[simp]:"map_poly of_real (smult s p) = smult (of_real s) (map_poly of_real p)" 
  apply (rule poly_eqI)
  by (auto simp add: coeff_map_poly)    

lemma of_real_poly_map_mult[simp]:"map_poly of_real (p*q) = map_poly of_real p * map_poly of_real q"
  by (induct p,intro poly_eqI,auto)
    
lemma of_real_poly_map_poly:
  "of_real (poly p x) = poly (map_poly of_real p) (of_real x)" 
  by (induct p,auto)    

lemma of_real_poly_map_power:"map_poly of_real (p^n) = (map_poly of_real p) ^ n"
  by (induct n,auto)

(*FIXME: not duplicate*)
lemma of_real_poly_eq_iff [simp]: "map_poly of_real p = map_poly of_real q p = q"
  by (auto simp: poly_eq_iff coeff_map_poly)

(*FIXME: not duplicate*)
lemma of_real_poly_eq_0_iff [simp]: "map_poly of_real p = 0 p = 0"
  by (auto simp: poly_eq_iff coeff_map_poly)

subsection More about @{term order}

lemma order_multiplicity_eq:
  assumes "p0"
  shows "order a p = multiplicity [:-a,1:] p"
  by (metis assms multiplicity_eqI order_1 order_2)

lemma order_gcd:
  assumes "p0" "q0"
  shows "order x (gcd p q) = min (order x p) (order x q)"
proof -
  have "prime [:- x, 1:]" 
    apply (auto simp add: prime_elem_linear_poly normalize_poly_def  intro!:primeI)
    by (simp add: pCons_one)
  then show ?thesis  
    using assms
    by (auto simp add:order_multiplicity_eq intro:multiplicity_gcd)
qed

lemma order_linear[simp]: "order x [:-a,1:] = (if x=a then 1 else 0)"
  by (auto simp add:order_power_n_n[where n=1,simplified] order_0I)
  
lemma map_poly_order_of_real:
  assumes "p0"
  shows "order (of_real t) (map_poly of_real p) = order t p" using assms
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  then have "order t p = 0" using order_root by blast
  moreover have "poly (map_poly of_real p) (of_real x) 0" for x
    apply (subst of_real_poly_map_poly[symmetric])
    using no_proots order_root by simp
  then have "order (of_real t) (map_poly of_real p) = 0"
    using order_root by blast
  ultimately show ?case by auto
next
  case (root a p)
  define a1 where "a1=[:-a,1:]"
  have [simp]:"a10" "p0" unfolding a1_def using root(2by auto
  have "order (of_real t) (map_poly of_real a1) = order t a1"
    unfolding a1_def by simp
  then show ?case 
    apply (fold a1_def)
    by (simp add:order_mult root)
qed

lemma order_pcompose:
  assumes "pcompose p q0"
  shows "order x (pcompose p q) = order x (q-[:poly q x:]) * order (poly q x) p" 
  using pcompose p q0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  have "order x (p p q) = 0"
    apply (rule order_0I)
    using no_proots by (auto simp:poly_pcompose)
  moreover have "order (poly q x) p = 0"
    apply (rule order_0I)
    using no_proots by (auto simp:poly_pcompose)
  ultimately show ?case by auto
next
  case (root a p)
  define a1 where "a1=[:-a,1:]"
  have [simp]: "a10" "p0" "a1 p q 0" "p p q 0" 
    subgoal using root(2unfolding a1_def by simp
    subgoal using root(2by auto
    using root(2by (fold a1_def,auto simp:pcompose_mult)
  have "order x ((a1 * p) p q) = order x (a1 p q) + order x (p p q)"
    unfolding pcompose_mult by (auto simp: order_mult)
  also have "... = order x (q-[:poly q x:]) * (order (poly q x) a1 + order (poly q x) p)"
  proof -
    have "order x (a1 p q) = order x (q-[:poly q x:]) * order (poly q x) a1"
      unfolding a1_def 
      apply (auto simp: pcompose_pCons algebra_simps diff_conv_add_uminus )
      by (simp add: order_0I)
    moreover have "order x (p p q) = order x (q - [:poly q x:]) * order (poly q x) p"
      apply (rule root.hyps)
      by auto
    ultimately show ?thesis by (auto simp:algebra_simps)
  qed
  also have "... = order x (q - [:poly q x:]) * order (poly q x) (a1 * p)"
    by (auto simp:order_mult)
  finally show ?case unfolding a1_def .
qed

subsection Polynomial roots / zeros

definition proots_within::"'a::comm_semiring_0 poly ==> 'a set ==> 'a set" where
  "proots_within p s = {xs. poly p x=0}"

abbreviation proots::"'a::comm_semiring_0 poly ==> 'a set" where
  "proots p proots_within p UNIV"

lemma proots_def: "proots p = {x. poly p x=0}" 
  unfolding proots_within_def by auto 

lemma proots_within_empty[simp]:
  "proots_within p {} = {}" unfolding proots_within_def by auto

lemma proots_within_0[simp]:
  "proots_within 0 s = s" unfolding proots_within_def by auto

lemma proots_withinI[intro,simp]:
  "poly p x=0 ==> xs ==> xproots_within p s"
  unfolding proots_within_def by auto

lemma proots_within_iff[simp]:
  "xproots_within p s poly p x=0 xs"
  unfolding proots_within_def by auto

lemma proots_within_union:
  "proots_within p A proots_within p B = proots_within p (A B)"
  unfolding proots_within_def by auto

lemma proots_within_times:
  fixes s::"'a::{semiring_no_zero_divisors,comm_semiring_0} set"
  shows "proots_within (p*q) s = proots_within p s proots_within q s"
  unfolding proots_within_def by auto

lemma proots_within_gcd:
  fixes s::"'a::{factorial_ring_gcd,semiring_gcd_mult_normalize} set"
  shows "proots_within (gcd p q) s= proots_within p s proots_within q s"
  unfolding proots_within_def 
  by (auto simp add: poly_eq_0_iff_dvd) 

lemma proots_within_inter:
  "NO_MATCH UNIV s ==> proots_within p s = proots p s" 
  unfolding proots_within_def by auto

lemma proots_within_proots[simp]:
  "proots_within p s proots p"
  unfolding proots_within_def by auto

lemma finite_proots[simp]: 
  fixes p :: "'a::idom poly"
  shows "p0 ==> finite (proots_within p s)"
  unfolding proots_within_def using poly_roots_finite by fast

lemma proots_within_pCons_1_iff:
  fixes a::"'a::idom"
  shows "proots_within [:-a,1:] s = (if as then {a} else {})"
    "proots_within [:a,-1:] s = (if as then {a} else {})"
  by (cases "as",auto)

lemma proots_within_uminus[simp]:
  fixes p :: "'a::comm_ring poly"
  shows "proots_within (- p) s = proots_within p s"
  by auto

lemma proots_within_smult:
  fixes a::"'a::{semiring_no_zero_divisors,comm_semiring_0}"
  assumes "a0"
  shows "proots_within (smult a p) s = proots_within p s"
  unfolding proots_within_def using assms by auto 

subsection Polynomial roots counting multiplicities.

(*counting the number of proots WITH MULTIPLICITIES within a set*)
definition proots_count::"'a::idom poly ==> 'a set ==> nat" where
  "proots_count p s = (rproots_within p s. order r p)"  

lemma proots_count_emtpy[simp]:"proots_count p {} = 0"
  unfolding proots_count_def by auto

lemma proots_count_times:
  fixes s :: "'a::idom set"
  assumes "p*q0"
  shows "proots_count (p*q) s = proots_count p s + proots_count q s"
proof -
  define pts where "pts=proots_within p s" 
  define qts where "qts=proots_within q s"
  have [simp]: "finite pts" "finite qts" 
    using p*q0 unfolding pts_def qts_def by auto
  have "(rpts qts. order r p) = (rpts. order r p)" 
  proof (rule comm_monoid_add_class.sum.mono_neutral_cong_right,simp_all)
    show "ipts qts - pts. order i p = 0" 
      unfolding pts_def qts_def proots_within_def using order_root by fastforce
  qed
  moreover have "(rpts qts. order r q) = (rqts. order r q)" 
  proof (rule comm_monoid_add_class.sum.mono_neutral_cong_right,simp_all)
    show "ipts qts - qts. order i q = 0" 
      unfolding pts_def qts_def proots_within_def using order_root by fastforce
  qed
  ultimately show ?thesis unfolding proots_count_def
    apply (simp add:proots_within_times order_mult[OF p*q0] sum.distrib)
    apply (fold pts_def qts_def)
    by auto
qed

lemma proots_count_power_n_n:
  shows "proots_count ([:- a, 1:]^n) s = (if as n>0 then n else 0)"
proof -
  have "proots_within ([:- a, 1:] ^ n) s= (if as n>0 then {a} else {})"
    unfolding proots_within_def by auto
  thus ?thesis unfolding proots_count_def using order_power_n_n by auto
qed

lemma degree_proots_count:
  fixes p::"complex poly"
  shows "degree p = proots_count p UNIV"
proof (induct "degree p" arbitrary:p )
  case 0
  then obtain c where c_def:"p=[:c:]" using degree_eq_zeroE by auto
  then show ?case unfolding proots_count_def 
    apply (cases "c=0")
    by (auto intro!:sum.infinite simp add:infinite_UNIV_char_0 order_0I)
next
  case (Suc n)
  then have "degree p0" and "p0" by auto
  obtain z where "poly p z = 0" 
    using Fundamental_Theorem_Algebra.fundamental_theorem_of_algebra degree p0 constant_degree[of p]
    by auto
  define onez where "onez=[:-z,1:]" 
  have [simp]: "onez0" "degree onez = 1" unfolding onez_def by auto
  obtain q where q_def:"p= onez * q" 
    using poly_eq_0_iff_dvd poly p z = 0 dvdE unfolding onez_def by blast
  hence "q0" using p0 by auto
  hence "n=degree q" using degree_mult_eq[of onez q] Suc n = degree p
    apply (fold q_def)
    by auto
  hence "degree q = proots_count q UNIV" using Suc.hyps(1by simp
  moreover have " Suc 0 = proots_count onez UNIV" 
    unfolding onez_def using proots_count_power_n_n[of z 1 UNIV]
    by auto
  ultimately show ?case 
    unfolding q_def using degree_mult_eq[of onez q] proots_count_times[of onez q UNIV] q0
    by auto
qed

lemma proots_count_smult:
  fixes a::"'a::{semiring_no_zero_divisors,idom}"
  assumes "a0"
  shows "proots_count (smult a p) s= proots_count p s"
proof (cases "p=0")
  case True
  then show ?thesis by auto
next
  case False
  then show ?thesis 
    unfolding proots_count_def
    using order_smult[OF assms] proots_within_smult[OF assms] by auto
qed


lemma proots_count_pCons_1_iff:
  fixes a::"'a::idom"
  shows "proots_count [:-a,1:] s = (if as then 1 else 0)"
  unfolding proots_count_def 
  by (cases "as",auto simp add:proots_within_pCons_1_iff order_power_n_n[of _ 1,simplified])

lemma proots_count_uminus[simp]:
  "proots_count (- p) s = proots_count p s"
  unfolding proots_count_def by simp

lemma card_proots_within_leq:
  assumes "p0"
  shows "proots_count p s card (proots_within p s)" using assms
proof (induct rule:poly_root_induct[of _ "λx. xs"])
  case 0
  then show ?case unfolding proots_within_def proots_count_def by auto
next
  case (no_roots p)
  then have "proots_within p s = {}" by auto
  then show ?case unfolding proots_count_def by auto
next
  case (root a p)
  have "card (proots_within ([:- a, 1:] * p) s)
       card (proots_within [:- a, 1:] s)+card (proots_within p s)" 
    unfolding proots_within_times by (auto simp add:card_Un_le)
  also have "... 1+ proots_count p s"
  proof -
    have "card (proots_within [:- a, 1:] s) 1"
    proof (cases "as")
      case True
      then have "proots_within [:- a, 1:] s = {a}" by auto
      then show ?thesis by auto
    next
      case False
      then have "proots_within [:- a, 1:] s = {}" by auto
      then show ?thesis by auto
    qed
    moreover have "card (proots_within p s) proots_count p s"
      apply (rule root.hyps)
      using root by auto
    ultimately show ?thesis by auto
  qed
  also have "... = proots_count ([:- a,1:] * p) s"
    apply (subst proots_count_times)
    subgoal by (metis mult_eq_0_iff pCons_eq_0_iff root.prems zero_neq_one)  
    using root by (auto simp add:proots_count_pCons_1_iff)
  finally have "card (proots_within ([:- a, 1:] * p) s) proots_count ([:- a, 1:] * p) s" .
  then show ?case 
    by (metis (no_types, opaque_lifting) add.inverse_inverse add.inverse_neutral minus_pCons 
        mult_minus_left proots_count_uminus proots_within_uminus)
qed

(*FIXME: not duplicate*)
lemma proots_count_0_imp_empty:
  assumes "proots_count p s=0" "p0"
  shows "proots_within p s = {}"
proof -
  have "card (proots_within p s) = 0"
    using card_proots_within_leq[OF p0,of s] proots_count p s=0 by auto
  moreover have "finite (proots_within p s)" using p0 by auto
  ultimately show ?thesis by auto
qed

lemma proots_count_leq_degree:
  assumes "p0"
  shows "proots_count p s degree p" using assms
proof (induct rule:poly_root_induct[of _ "λx. xs"])
  case 0
  then show ?case by auto
next
  case (no_roots p)
  then have "proots_within p s = {}" by auto
  then show ?case unfolding proots_count_def by auto
next
  case (root a p)
  have "proots_count ([:a, - 1:] * p) s = proots_count [:a, - 1:] s + proots_count p s"
    apply (subst proots_count_times)
    using root by auto
  also have "... = 1 + proots_count p s"
  proof -
    have "proots_count [:a, - 1:] s =1"
      by (metis (no_types, lifting) add.inverse_inverse add.inverse_neutral minus_pCons 
          proots_count_pCons_1_iff proots_count_uminus root.hyps(1))
    then show ?thesis by auto
  qed
  also have "... degree ([:a,-1:] * p)" 
    apply (subst degree_mult_eq)
    subgoal by auto
    subgoal using root by auto
    subgoal using root by (simp add: p 0)
    done
  finally show ?case .
qed

(*TODO: not a duplicate*)
lemma proots_count_union_disjoint:
  assumes "A B = {}" "p0"
  shows "proots_count p (A B) = proots_count p A + proots_count p B"
  unfolding proots_count_def 
  apply (subst proots_within_union[symmetric])
  apply (subst sum.union_disjoint)
  using assms by auto

lemma proots_count_cong:
  assumes order_eq:"xs. order x p = order x q" and "p0" and "q0"
  shows "proots_count p s = proots_count q s" unfolding proots_count_def
proof (rule sum.cong)
  have "poly p x = 0 poly q x = 0" when "xs" for x
    using order_eq that by (simp add: assms(2) assms(3) order_root)
  then show "proots_within p s = proots_within q s" by auto
  show "x. x proots_within q s ==> order x p = order x q"
    using order_eq by auto
qed

lemma proots_count_of_real:
  assumes "p0"
  shows "proots_count (map_poly of_real p) ((of_real::_==>'a::{real_algebra_1,idom}) ` s)
            = proots_count p s"
proof -
  define k where "k=(of_real::_==>'a)"
  have "proots_within (map_poly of_real p) (k ` s) =k ` (proots_within p s)"
    unfolding proots_within_def k_def by (auto simp add:of_real_poly_map_poly[symmetric])
  then have "proots_count (map_poly of_real p) (k ` s)
                = (rk ` (proots_within p s). order r (map_poly of_real p))"
    unfolding proots_count_def by simp
  also have "... = sum ((λr. order r (map_poly of_real p)) k) (proots_within p s)"
    apply (subst sum.reindex) 
    unfolding k_def by (auto simp add: inj_on_def)
  also have "... = proots_count p s" unfolding proots_count_def
    apply (rule sum.cong)
    unfolding k_def comp_def using p0 by (auto simp add:map_poly_order_of_real) 
  finally show ?thesis unfolding k_def .
qed

(*Is field really necessary here?*)
lemma proots_pcompose:
  fixes p q::"'a::field poly"
  assumes "p0" "degree q=1"
  shows "proots_count (pcompose p q) s = proots_count p (poly q ` s)"
proof -
  obtain a b where ab:"q=[:a,b:]" "b0"
    using degree q=1 degree_eq_oneE by metis
  define f where "f=(λy. (y-a)/b)"
  have f_eq:"f (poly q x) = x" "poly q (f x) = x" for x
    unfolding f_def using ab by auto
  have "proots_count (p p q) s = (r f ` proots_within p (poly q ` s). order r (p p q))" 
    unfolding proots_count_def
    apply (rule arg_cong2[where f =sum])
    apply (auto simp:poly_pcompose proots_within_def f_eq)
    by (metis (mono_tags, lifting) f_eq(1) image_eqI mem_Collect_eq)
  also have "... = (xproots_within p (poly q ` s). order (f x) (p p q))"
    apply (subst sum.reindex)
    subgoal unfolding f_def inj_on_def using b0 by auto
    by simp
  also have "... = (xproots_within p (poly q ` s). order x p)"
  proof -
    have "p p q 0" using assms(1) assms(2) pcompose_eq_0 by force
    moreover have "order (f x) (q - [:x:]) = 1" for x 
    proof -
      have "order (f x) (q - [:x:]) = order (f x) (smult b [:-((x - a) / b),1:])"
        unfolding f_def using ab by auto
      also have "... = 1"
        apply (subst order_smult)
        using b0 unfolding f_def by auto
      finally show ?thesis .
    qed
    ultimately have "order (f x) (p p q) = order x p" for x
      apply (subst order_pcompose)
      using f_eq by auto
    then show ?thesis by auto
  qed
  also have "... = proots_count p (poly q ` s)"
    unfolding proots_count_def by auto
  finally show ?thesis .
qed

subsection Composition of a polynomial and a rational function

(*composition of a polynomial and a rational function. Maybe a more general version in the future?*)
definition fcompose::"'a ::field poly ==> 'a poly ==> 'a poly ==> 'a poly" where
  "fcompose p q r = fst (fold_coeffs (λa (c,d). (d*[:a:] + q * c,r*d)) p (0,1))"

lemma fcompose_0 [simp]: "fcompose 0 q r = 0"
  by (simp add: fcompose_def)

lemma fcompose_const[simp]:"fcompose [:a:] q r = [:a:]"
  unfolding fcompose_def by (cases "a=0") auto

lemma fcompose_pCons: 
  "fcompose (pCons a p) q1 q2 = smult a (q2^(degree (pCons a p))) + q1 * fcompose p q1 q2"
proof (cases "p=0")
  case False
  define ff where "ff=(λa (c, d). (d * [:a:] + q1 * c, q2 * d))"
  define fc where "fc=fold_coeffs ff p (0, 1)"
  have snd_ff:"snd fc = (if p=0 then 1 else q2^(degree p + 1))" unfolding fc_def
    apply (induct p)
    subgoal by simp
    subgoal for a p
      by (auto simp add:ff_def split:if_splits prod.splits)
    done

  have "fcompose (pCons a p) q1 q2 = fst (fold_coeffs ff (pCons a p) (0, 1))"
    unfolding fcompose_def ff_def by simp
  also have "... = fst (ff a fc)"
    using False unfolding fc_def by auto
  also have "... = snd fc * [:a:] + q1 * fst fc"
    unfolding ff_def by (auto split:prod.splits)
  also have "... = smult a (q2^(degree (pCons a p))) + q1 * fst fc"
    using snd_ff False by auto
  also have "... = smult a (q2^(degree (pCons a p))) + q1 * fcompose p q1 q2"
    unfolding fc_def ff_def fcompose_def by simp
  finally show ?thesis .
qed simp

lemma fcompose_uminus:
  "fcompose (-p) q r = - fcompose p q r"
  by (induct p) (auto simp:fcompose_pCons)

lemma fcompose_add_less:
  assumes "degree p1 > degree p2"
  shows "fcompose (p1+p2) q1 q2
            = fcompose p1 q1 q2 + q2^(degree p1-degree p2) * fcompose p2 q1 q2"
  using assms
proof (induction p1 p2 rule: poly_induct2)
  case (pCons a1 p1 a2 p2)
  have ?case when "p2=0"
    using that by (simp add:fcompose_pCons smult_add_left)
  moreover have ?case when "p20" "¬ degree p2 < degree p1"
    using that pCons(2by auto
  moreover have ?case when "p20" "degree p2< degree p1"
  proof -
    define d1 d2 where "d1=degree (pCons a1 p1)" and "d2=degree (pCons a2 p2) "
    define fp1 fp2 where "fp1= fcompose p1 q1 q2" and "fp2=fcompose p2 q1 q2"

    have "fcompose (pCons a1 p1 + pCons a2 p2) q1 q2
            = fcompose (pCons (a1+a2) (p1+p2)) q1 q2"
      by simp
    also have "... = smult (a1 + a2) (q2 ^ d1) + q1 * fcompose (p1 + p2) q1 q2"
    proof -
      have "degree (pCons (a1 + a2) (p1 + p2)) = d1"
        unfolding d1_def using that degree_add_eq_left by fastforce
      then show ?thesis unfolding fcompose_pCons by simp
    qed
    also have "... = smult (a1 + a2) (q2 ^ d1) + q1 * (fp1 + q2 ^ (d1 - d2) * fp2)"
    proof -
      have "degree p1 - degree p2 = d1 - d2"
        unfolding d1_def d2_def using that by simp
      then show ?thesis 
        unfolding pCons(1)[OF that(2),folded fp1_def fp2_def] by simp
    qed
    also have "... = fcompose (pCons a1 p1) q1 q2 + q2 ^ (d1 - d2)
                        * fcompose (pCons a2 p2) q1 q2"
    proof -
      have "d1 > d2" unfolding d1_def d2_def using that by auto
      then show ?thesis
        unfolding fcompose_pCons
        apply (fold d1_def d2_def fp1_def fp2_def)
        by (simp add:algebra_simps smult_add_left power_add[symmetric])
    qed
    finally show ?thesis unfolding d1_def d2_def .
  qed
  ultimately show ?case by blast
qed simp

lemma fcompose_add_eq:
  assumes "degree p1 = degree p2"
  shows "q2^(degree p1 - degree (p1+p2)) * fcompose (p1+p2) q1 q2
            = fcompose p1 q1 q2 + fcompose p2 q1 q2"
  using assms
proof (induction p1 p2 rule: poly_induct2)
  case (pCons a1 p1 a2 p2)
  have ?case when "p1+p2=0"
  proof -
    have "p2=-p1" using that by algebra
    then show ?thesis by (simp add:fcompose_pCons fcompose_uminus smult_add_left)
  qed
  moreover have ?case when "p1=0"
  proof -
    have "p2=0"
      using pCons(2) that by (auto split:if_splits)
    then show ?thesis using that by simp
  qed
  moreover have ?case when "p10" "p1+p20"
  proof -
    define d1 d2 dp where "d1=degree (pCons a1 p1)" and "d2=degree (pCons a2 p2)"
                            and "dp = degree p1 - degree (p1+p2)"
    define fp1 fp2 where "fp1= fcompose p1 q1 q2" and "fp2=fcompose p2 q1 q2"

    have "q2 ^ (degree (pCons a1 p1) - degree (pCons a1 p1 + pCons a2 p2)) *
             fcompose (pCons a1 p1 + pCons a2 p2) q1 q2
                = q2 ^ dp * fcompose (pCons (a1+a2) (p1 +p2)) q1 q2"
      unfolding dp_def using that by auto
    also have "... = smult (a1 + a2) (q2 ^ d1) + q1 * (q2 ^ dp * fcompose (p1 + p2) q1 q2)"
    proof -
      have "degree p1 degree (p1 + p2)" 
        by (metis degree_add_le degree_pCons_eq_if not_less_eq_eq order_refl pCons.prems zero_le)
      then show ?thesis 
        unfolding fcompose_pCons dp_def d1_def using that
        by (simp add:algebra_simps power_add[symmetric])
    qed
    also have "... = smult (a1 + a2) (q2 ^ d1) + q1 * (fp1 + fp2)"
      apply (subst pCons(1)[folded dp_def fp1_def fp2_def])
      subgoal by (metis degree_pCons_eq_if diff_Suc_Suc diff_zero not_less_eq_eq pCons.prems zero_le)
      subgoal by simp
      done
    also have "... = fcompose (pCons a1 p1) q1 q2 + fcompose (pCons a2 p2) q1 q2"
    proof -
      have *:"d1 = degree (pCons a2 p2)"
        unfolding d1_def using pCons(2by simp
      show ?thesis 
        unfolding fcompose_pCons
        apply (fold d1_def fp1_def fp2_def *)
        by (simp add:smult_add_left algebra_simps)
    qed
    finally show ?thesis .
  qed
  ultimately show ?case by blast
qed simp

lemma fcompose_add_const:
  "fcompose ([:a:] + p) q1 q2 = smult a (q2 ^ degree p) + fcompose p q1 q2"
  apply (cases p)
  by (auto simp add:fcompose_pCons smult_add_left)

lemma fcompose_smult: "fcompose (smult a p) q1 q2 = smult a (fcompose p q1 q2)"
  by (induct p) (simp_all add:fcompose_pCons smult_add_right)

lemma fcompose_mult: "fcompose (p1*p2) q1 q2 = fcompose p1 q1 q2 * fcompose p2 q1 q2"
proof (induct p1)
  case 0
  then show ?case by simp
next
  case (pCons a p1)
  have ?case when "p1=0 p2=0" 
    using that by (auto simp add:fcompose_smult)
  moreover have ?case when "p10" "p20" "a=0"
    using that by (simp add:fcompose_pCons pCons)
  moreover have ?case when "p10" "p20" "a0"
  proof -
    have "fcompose (pCons a p1 * p2) q1 q2
            = fcompose (pCons 0 (p1 * p2) + smult a p2) q1 q2"
      by (simp add:algebra_simps)
    also have "... = fcompose (pCons 0 (p1 * p2)) q1 q2
                        + q2 ^ (degree p1 +1) * fcompose (smult a p2) q1 q2"
    proof -
      have "degree (pCons 0 (p1 * p2)) > degree (smult a p2)"
        using that by (simp add: degree_mult_eq)
      from fcompose_add_less[OF this,of q1 q2] that 
      show ?thesis by (simp add:degree_mult_eq)
    qed
    also have "... = fcompose (pCons a p1) q1 q2 * fcompose p2 q1 q2"
      using that by (simp add:fcompose_pCons fcompose_smult pCons algebra_simps)
    finally show ?thesis .
  qed
  ultimately show ?case by blast
qed

lemma fcompose_poly:
  assumes "poly q2 x0"
  shows "poly p (poly q1 x/poly q2 x) = poly (fcompose p q1 q2) x / poly (q2^(degree p)) x"
  apply (induct p)
  using assms by (simp_all add:fcompose_pCons field_simps)

lemma poly_fcompose:
   assumes "poly q2 x0"
   shows "poly (fcompose p q1 q2) x = poly p (poly q1 x/poly q2 x) * (poly q2 x)^(degree p)"
  using fcompose_poly[OF assms] assms by (auto simp add:field_simps)
lemma poly_fcompose_0_denominator:
  assumes "poly q2 x=0"
  shows "poly (fcompose p q1 q2) x = poly q1 x ^ degree p * lead_coeff p"
  apply (induct p)
  using assms by (auto simp add:fcompose_pCons)

lemma fcompose_0_denominator:"fcompose p q1 0 = smult (lead_coeff p) (q1^degree p)"
  apply (induct p)
  by (auto simp:fcompose_pCons)

lemma fcompose_nzero:
  fixes p::"'a::field poly"
  assumes "p0" and "q20" and nconst:"c. q1 smult c q2"
      and infi:"infinite (UNIV::'a set)"
  shows "fcompose p q1 q2 0" using p0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  have False when "fcompose p q1 q2 = 0"
  proof -
    obtain x where "poly q2 x0" 
    proof -
      have "finite (proots q2)" using q20 by auto
      then have "x. poly q2 x0" 
        by (meson UNIV_I ex_new_if_finite infi proots_withinI)
      then show ?thesis using that by auto
    qed
    define y where "y = poly q1 x / poly q2 x"
    have "poly p y = 0"
      using fcompose p q1 q2 = 0 fcompose_poly[OF poly q2 x0,of p q1,folded y_def] 
      by simp
    then show False using no_proots(1by auto
  qed
  then show ?case by auto
next
  case (root a p)
  have "fcompose [:- a, 1:] q1 q2 0" 
    unfolding fcompose_def using nconst[rule_format,of a]
    by simp
  moreover have "fcompose p q1 q2 0" 
    using root by fastforce
  ultimately show ?case unfolding fcompose_mult by auto
qed

subsection Bijection (@{term bij_betw}) and the number of polynomial roots

lemma proots_fcompose_bij_eq:
  fixes p::"'a::field poly"
  assumes bij:"bij_betw (λx. poly q1 x/poly q2 x) A B" and "p0" 
      and nzero:"xA. poly q2 x0"
      and max_deg: "max (degree q1) (degree q2) 1"
      and nconst:"c. q1 smult c q2"
      and infi:"infinite (UNIV::'a set)"
  shows "proots_count p B = proots_count (fcompose p q1 q2) A"
  using p0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  have "proots_count p B = 0"
  proof -
    have "proots_within p B = {}"
      using no_proots by auto
    then show ?thesis unfolding proots_count_def by auto
  qed
  moreover have "proots_count (fcompose p q1 q2) A = 0"
  proof -
    have "proots_within (fcompose p q1 q2) A = {}"
      using no_proots unfolding proots_within_def
      by (smt (verit) div_0 empty_Collect_eq fcompose_poly nzero)
    then show ?thesis unfolding proots_count_def by auto
  qed
  ultimately show ?case by auto
next
  case (root b p)
  have "proots_count ([:- b, 1:] * p) B = proots_count [:- b, 1:] B + proots_count p B"
    using proots_count_times[OF [:- b, 1:] * p 0by simp
  also have "... = proots_count (fcompose [:- b, 1:] q1 q2) A
                    + proots_count (fcompose p q1 q2) A" 
  proof -
    define g where "g=(λx. poly q1 x/poly q2 x)"

    have "proots_count [:- b, 1:] B = proots_count (fcompose [:- b, 1:] q1 q2) A" 
    proof (cases "bB")
      case True
      then have "proots_count [:- b, 1:] B = 1"
        unfolding proots_count_pCons_1_iff by simp
      moreover have "proots_count (fcompose [:- b, 1:] q1 q2) A = 1"
      proof -
        obtain a where "b=g a" "aA"
          using bij[folded g_def] True 
          by (metis bij_betwE bij_betw_the_inv_into f_the_inv_into_f_bij_betw)
        define qq where "qq=q1 - smult b q2"
        have qq_0:"poly qq a=0" and qq_deg: "degree qq1" and qq0
          unfolding qq_def
          subgoal using b=g a nzero[rule_format,OF aAunfolding g_def by auto
          subgoal using max_deg by (simp add: degree_diff_le)
          subgoal using nconst[rule_format,of b] by auto
          done
        have "proots_within qq A = {a}" 
        proof -
          have "aproots_within qq A" 
            using qq_0 aA by auto
          moreover have "card (proots_within qq A) = 1" 
          proof -
            have "finite (proots_within qq A)" using qq0 by simp
            moreover have "proots_within qq A {}"
              using aproots_within qq A by auto
            ultimately have "card (proots_within qq A) 0" by auto
            moreover have "card (proots_within qq A) 1" 
              by (meson qq 0 card_proots_within_leq le_trans proots_count_leq_degree qq_deg)
            ultimately show ?thesis by auto
          qed
          ultimately show ?thesis by (metis card_1_singletonE singletonD)
        qed
        moreover have "order a qq=1" 
          by (metis One_nat_def qq 0 le_antisym le_zero_eq not_less_eq_eq order_degree
                order_root qq_0 qq_deg)
        ultimately show ?thesis unfolding fcompose_def proots_count_def qq_def  
          by auto
      qed
      ultimately show ?thesis by auto
    next
      case False
      then have "proots_count [:- b, 1:] B = 0"
        unfolding proots_count_pCons_1_iff by simp
      moreover have "proots_count (fcompose [:- b, 1:] q1 q2) A = 0"
      proof -
        have "proots_within (fcompose [:- b, 1:] q1 q2) A = {}"
        proof (rule ccontr)
          assume "proots_within (fcompose [:- b, 1:] q1 q2) A {}"
          then obtain a where "aA" "poly q1 a = b * poly q2 a"
            unfolding fcompose_def proots_within_def by auto
          then have "b = g a"
            unfolding g_def using nzero[rule_format,OF aAby auto
          then have "bB" using aA bij[folded g_def] using bij_betwE by blast
          then show False using False by auto
        qed  
        then show ?thesis unfolding proots_count_def by auto
      qed      
      ultimately show ?thesis by simp
    qed
    moreover have "proots_count p B = proots_count (fcompose p q1 q2) A" 
      apply (rule root.hyps)
      using mult_eq_0_iff root.prems by blast
    ultimately show ?thesis by auto
  qed
  also have "... = proots_count (fcompose ([:- b, 1:] * p) q1 q2) A"
  proof (cases "A={}")
    case False
    have "fcompose [:- b, 1:] q1 q2 0" 
      using nconst[rule_format,of b] unfolding fcompose_def by auto
    moreover have "fcompose p q1 q2 0" 
      apply (rule fcompose_nzero[OF _ _ nconst infi])
      subgoal using [:- b, 1:] * p 0 by auto
      subgoal using nzero False by auto
      done
    ultimately show ?thesis unfolding fcompose_mult
      apply (subst proots_count_times)
      by auto
  qed auto
  finally show ?case .
qed

lemma proots_card_fcompose_bij_eq:
  fixes p::"'a::field poly"
  assumes bij:"bij_betw (λx. poly q1 x/poly q2 x) A B" and "p0" 
      and nzero:"xA. poly q2 x0"
      and max_deg: "max (degree q1) (degree q2) 1"
      and nconst:"c. q1 smult c q2"
      and infi:"infinite (UNIV::'a set)"
  shows "card (proots_within p B) = card (proots_within (fcompose p q1 q2) A)"
  using p0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  have "proots_within p B = {}" using no_proots by auto
  moreover have "proots_within (fcompose p q1 q2) A = {}" 
    using no_proots fcompose_poly 
    by (smt (verit) Collect_empty_eq divide_eq_0_iff nzero proots_within_def)
  ultimately show ?case by auto
next
  case (root b p)
  then have [simp]:"p0" by auto

  have ?case when "bB poly p b=0"
  proof -
    have "proots_within ([:- b, 1:] * p) B = proots_within p B"
      using that by auto
    moreover have "proots_within (fcompose ([:- b, 1:] * p) q1 q2) A
        = proots_within (fcompose p q1 q2) A"
      using that nzero unfolding fcompose_mult proots_within_times 
      apply (auto simp add: poly_fcompose)
      using bij bij_betwE by blast
    ultimately show ?thesis using root by auto
  qed
  moreover have ?case when "bB" "poly p b0"
  proof -
    define bb where "bb=[:- b, 1:]"
    have "card (proots_within (bb * p) B) = card {b} + card (proots_within p B)"
    proof -
      have "proots_within bb B = {b}" 
        using that unfolding bb_def by auto
      then show ?thesis unfolding proots_within_times
        apply (subst card_Un_disjoint)
        by (use that in auto)
    qed
    also have "... = 1 + card (proots_within (fcompose p q1 q2) A)"
      using root.hyps by simp
    also have "... = card (proots_within (fcompose (bb * p) q1 q2) A)"
      unfolding proots_within_times fcompose_mult
    proof (subst card_Un_disjoint) 
      obtain a where b_poly:"b=poly q1 a / poly q2 a" and "aA" 
        by (metis (no_types, lifting) b B bij bij_betwE bij_betw_the_inv_into 
            f_the_inv_into_f_bij_betw)
      define bbq pq where "bbq=fcompose bb q1 q2" and "pq=fcompose p q1 q2"
      have bbq_0:"poly bbq a=0" and bbq_deg: "degree bbq1" and "bbq0"
        unfolding bbq_def bb_def 
        subgoal using a A b_poly nzero poly_fcompose by fastforce
        subgoal by (metis (no_types, lifting) degree_add_le degree_pCons_eq_if degree_smult_le 
           dual_order.trans fcompose_const fcompose_pCons max.boundedE max_deg mult_cancel_left2 
           one_neq_zero one_poly_eq_simps(1) power.simps)
        subgoal by (metis a A poly (fcompose [:- b, 1:] q1 q2) a = 0 fcompose_nzero infi 
                  nconst nzero one_neq_zero pCons_eq_0_iff)
        done
      show "finite (proots_within bbq A)" using bbq0 by simp
      show "finite (proots_within pq A)" unfolding pq_def 
        by (metis a A p 0 fcompose_nzero finite_proots infi nconst nzero poly_0 pq_def)
      have bbq_a:"proots_within bbq A = {a}"
      proof -
        have "aproots_within bbq A" 
          by (simp add: a A bbq_0)
        moreover have "card (proots_within bbq A) = 1" 
        proof -
          have "card (proots_within bbq A) 0" 
            using aproots_within bbq A finite (proots_within bbq A)
            by auto
          moreover have "card (proots_within bbq A) 1" 
            by (meson bbq 0 card_proots_within_leq le_trans proots_count_leq_degree bbq_deg)
          ultimately show ?thesis by auto
        qed
        ultimately show ?thesis by (metis card_1_singletonE singletonD)
      qed
      show "proots_within (bbq) A proots_within (pq) A = {}" 
        using b_poly bbq_a fcompose_poly nzero pq_def that(2by fastforce
      show "1 + card (proots_within pq A) = card (proots_within bbq A) + card (proots_within pq A)"
        using bbq_a by simp
    qed
    finally show ?thesis unfolding bb_def .
  qed
  ultimately show ?case by auto
qed 

lemma proots_pcompose_bij_eq:
  fixes p::"'a::idom poly"
  assumes bij:"bij_betw (λx. poly q x) A B" and "p0" 
      and q_deg: "degree q = 1"
  shows "proots_count p B = proots_count (p p q) A" using p0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by simp
next
  case (no_proots p)
  have "proots_count p B = 0"
  proof -
    have "proots_within p B = {}"
      using no_proots by auto
    then show ?thesis unfolding proots_count_def by auto
  qed
  moreover have "proots_count (p p q) A = 0"
  proof -
    have "proots_within (p p q) A = {}"
      using no_proots unfolding proots_within_def
      by (auto simp:poly_pcompose)
    then show ?thesis unfolding proots_count_def by auto
  qed
  ultimately show ?case by auto
next
  case (root b p)
  have "proots_count ([:- b, 1:] * p) B = proots_count [:- b, 1:] B + proots_count p B"
    using proots_count_times[OF [:- b, 1:] * p 0by simp
  also have "... = proots_count ([:- b, 1:] p q) A + proots_count (p p q) A"
  proof -
    have "proots_count [:- b, 1:] B = proots_count ([:- b, 1:] p q) A"
    proof (cases "bB")
      case True
      then have "proots_count [:- b, 1:] B = 1" 
        unfolding proots_count_pCons_1_iff by simp
      moreover have "proots_count ([:- b, 1:] p q) A = 1" 
      proof -
        obtain a where "b=poly q a" "aA"
          using True bij by (metis bij_betwE bij_betw_the_inv_into f_the_inv_into_f_bij_betw)
        define qq where "qq=[:- b:] + q"
        have qq_0:"poly qq a=0" and qq_deg: "degree qq1" and qq0
          unfolding qq_def
          subgoal using b=poly q a by auto
          subgoal using q_deg by (simp add: degree_add_le)
          subgoal using q_deg add.inverse_unique by force
          done
        have "proots_within qq A = {a}" 
        proof -
          have "aproots_within qq A" 
            using qq_0 aA by auto
          moreover have "card (proots_within qq A) = 1" 
          proof -
            have "finite (proots_within qq A)" using qq0 by simp
            moreover have "proots_within qq A {}"
              using aproots_within qq A by auto
            ultimately have "card (proots_within qq A) 0" by auto
            moreover have "card (proots_within qq A) 1" 
              by (meson qq 0 card_proots_within_leq le_trans proots_count_leq_degree qq_deg)
            ultimately show ?thesis by auto
          qed
          ultimately show ?thesis by (metis card_1_singletonE singletonD)
        qed
        moreover have "order a qq=1" 
          by (metis One_nat_def qq 0 le_antisym le_zero_eq not_less_eq_eq order_degree
                order_root qq_0 qq_deg)
        ultimately show ?thesis unfolding pcompose_def proots_count_def qq_def  
          by auto
      qed
      ultimately show ?thesis by auto
    next
      case False
      then have "proots_count [:- b, 1:] B = 0"
        unfolding proots_count_pCons_1_iff by simp
      moreover have "proots_count ([:- b, 1:] p q) A = 0"
      proof -
        have "proots_within ([:- b, 1:] p q) A = {}"
          unfolding pcompose_def 
          apply auto
          using False bij bij_betwE by blast
        then show ?thesis unfolding proots_count_def by auto
      qed      
      ultimately show ?thesis by simp
    qed
    moreover have "proots_count p B = proots_count (p p q) A"
      apply (rule root.hyps)
      using [:- b, 1:] * p 0 by auto
    ultimately show ?thesis by auto
  qed
  also have "... = proots_count (([:- b, 1:] * p) p q) A"
    unfolding pcompose_mult
    apply (subst proots_count_times)
    subgoal by (metis (no_types, lifting) One_nat_def add.right_neutral degree_0 degree_mult_eq
      degree_pCons_eq_if degree_pcompose mult_eq_0_iff one_neq_zero one_pCons pcompose_mult
      q_deg root.prems)
    by simp
  finally show ?case .
qed

lemma proots_card_pcompose_bij_eq:
  fixes p::"'a::idom poly"
  assumes bij:"bij_betw (λx. poly q x) A B" and "p0" 
      and q_deg: "degree q = 1"
  shows "card (proots_within p B) = card (proots_within (p p q) A)" using p0
proof (induct p rule:poly_root_induct_alt)
  case 0
  then show ?case by auto
next
  case (no_proots p)
  have "proots_within p B = {}" using no_proots by auto
  moreover have "proots_within (p p q) A = {}" using no_proots 
    by (simp add: poly_pcompose proots_within_def)
  ultimately show ?case by auto
next
  case (root b p)
  then have [simp]:"p0" by auto
  have ?case when "bB poly p b=0"
  proof -
    have "proots_within ([:- b, 1:] * p) B = proots_within p B"
      using that by auto
    moreover have "proots_within (([:- b, 1:] * p) p q) A = proots_within (p p q) A"
      using that unfolding pcompose_mult proots_within_times
      apply (auto simp add: poly_pcompose)
      using bij bij_betwE by blast
    ultimately show ?thesis using root.hyps[OF p0by auto
  qed
  moreover have ?case when "bB" "poly p b0"
  proof -
    define bb where "bb=[:- b, 1:]"
    have "card (proots_within (bb * p) B) = card {b} + card (proots_within p B)"
    proof -
      have "proots_within bb B = {b}" 
        using that unfolding bb_def by auto
      then show ?thesis unfolding proots_within_times
        apply (subst card_Un_disjoint)
        by (use that in auto)
    qed
    also have "... = 1 + card (proots_within (p p q) A)"
      using root.hyps by simp
    also have "... = card (proots_within ((bb * p) p q) A)"
      unfolding proots_within_times pcompose_mult
    proof (subst card_Un_disjoint) 
      obtain a where "b=poly q a" "aA" 
        by (metis b B bij bij_betwE bij_betw_the_inv_into f_the_inv_into_f_bij_betw)
      define bbq pq where "bbq=bb p q" and "pq=p p q"
      have bbq_0:"poly bbq a=0" and bbq_deg: "degree bbq1" and "bbq0"
        unfolding bbq_def bb_def poly_pcompose
        subgoal using b=poly q a by auto
        subgoal using q_deg by (simp add: degree_add_le degree_pcompose)
        subgoal using pcompose_eq_0 q_deg by fastforce
        done
      show "finite (proots_within bbq A)" using bbq0 by simp
      show "finite (proots_within pq A)" unfolding pq_def 
        by (metis p 0 finite_proots pcompose_eq_0 q_deg zero_less_one) 
      have bbq_a:"proots_within bbq A = {a}"
      proof -
        have "aproots_within bbq A" 
          unfolding bb_def proots_within_def poly_pcompose bbq_def 
          using b=poly q a aA by simp
        moreover have "card (proots_within bbq A) = 1" 
        proof -
          have "card (proots_within bbq A) 0" 
            using aproots_within bbq A finite (proots_within bbq A)
            by auto
          moreover have "card (proots_within bbq A) 1" 
            by (meson bbq 0 card_proots_within_leq le_trans proots_count_leq_degree bbq_deg)
          ultimately show ?thesis by auto
        qed
        ultimately show ?thesis by (metis card_1_singletonE singletonD)
      qed
      show "proots_within (bbq) A proots_within (pq) A = {}" 
        using bbq_a b = poly q a that(2unfolding pq_def by (simp add:poly_pcompose)
      show "1 + card (proots_within pq A) = card (proots_within bbq A) + card (proots_within pq A)"
        using bbq_a by simp
    qed
    finally show ?thesis unfolding bb_def .
  qed
  ultimately show ?case by auto
qed

end

Messung V0.5 in Prozent
C=89 H=97 G=93

¤ Dauer der Verarbeitung: 0.15 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge