Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/Three_Circles/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 29.4.2026 mit Größe 40 kB image not shown  

Quelle  RRI_Misc.thy

  Sprache: Isabelle
 

section Misc results about polynomials

theory RRI_Misc imports 
  "HOL-Computational_Algebra.Computational_Algebra" 
  "Budan_Fourier.BF_Misc"
  "Polynomial_Interpolation.Ring_Hom_Poly"
begin

subsection Misc

declare pcompose_pCons[simp del]

lemma Setcompr_subset: "f P S. {f x | x. P x} S = ( x. P x f x S)" 
  by blast

lemma map_cong':
  assumes "xs = map h ys" and "y. y set ys ==> f (h y) = g y"
  shows "map f xs = map g ys"
  using assms map_replicate_trivial by simp

lemma nth_default_replicate_eq: 
    "nth_default dflt (replicate n x) i = (if i < n then x else dflt)"
  by (auto simp: nth_default_def)

lemma square_bounded_less: 
  fixes a b::"'a :: linordered_ring_strict"
  shows "-a < b b < a ==> b*b < a*a"
  by (metis (no_types, lifting) leD leI minus_less_iff minus_mult_minus mult_strict_mono'
      neg_less_eq_nonneg neg_less_pos verit_minus_simplify(4) zero_le_mult_iff zero_le_square)

lemma square_bounded_le: 
  fixes a b::"'a :: linordered_ring_strict"
  shows "-a b b a ==> b*b a*a"
  by (metis le_less minus_mult_minus square_bounded_less)

context vector_space
begin

lemma card_le_dim_spanning:
  assumes BV: "B V"
    and VB: "V span B"
    and fB: "finite B"
    and dVB: "dim V card B"
  shows "independent B"
proof -
  {
    fix a
    assume a: "a B" "a span (B - {a})"
    from a fB have c0: "card B 0"
      by auto
    from a fB have cb: "card (B - {a}) = card B - 1"
      by auto
    {
      fix x
      assume x: "x V"
      from a have eq: "insert a (B - {a}) = B"
        by blast
      from x VB have x': "x span B"
        by blast
      from span_trans[OF a(2), unfolded eq, OF x']
      have "x span (B - {a})" .
    }
    then have th1: "V span (B - {a})"
      by blast
    have th2: "finite (B - {a})"
      using fB by auto
    from dim_le_card[OF th1 th2]
    have c: "dim V card (B - {a})" .
    from c c0 dVB cb have False by simp
  }
  then show ?thesis
    unfolding dependent_def by blast
qed

end

subsection Misc results about polynomials

lemma smult_power: "smult (x^n) (p^n) = smult x p ^ n"
  apply (induction n)
  subgoal by fastforce 
  by (metis smult_power)

lemma reflect_poly_monom: "reflect_poly (monom n i) = monom n 0"
  apply (induction i)
  by (auto simp: coeffs_eq_iff coeffs_monom coeffs_reflect_poly)

lemma poly_eq_by_eval: 
  fixes P Q :: "'a::{comm_ring_1,ring_no_zero_divisors,ring_char_0} poly"
  assumes h: "x. poly P x = poly Q x" shows "P = Q"
proof -
  have "poly P = poly Q" using h by fast
  thus ?thesis by (auto simp: poly_eq_poly_eq_iff)
qed

lemma poly_binomial: 
  "[:(1::'a::comm_ring_1), 1:]^n = (kn. monom (of_nat (n choose k)) k)"
proof -
  have "[:(1::'a::comm_ring_1), 1:]^n = (monom 1 1 + 1)^n"
    by (metis (no_types, lifting) add.left_neutral add.right_neutral add_pCons
        monom_altdef pCons_one power_one_right smult_1_left)
  also have "... = (kn. of_nat (n choose k) * monom 1 1 ^ k)"
    apply (subst binomial_ring)
    by force
  also have "... = (kn. monom (of_nat (n choose k)) k)"
    by (auto simp: monom_altdef of_nat_poly)
  finally show ?thesis .
qed

lemma degree_0_iff: "degree P = 0 (a. P = [:a:])"
  by (meson degree_eq_zeroE degree_pCons_0)

interpretation poly_vs: vector_space smult
  by (simp add: vector_space_def smult_add_right smult_add_left)

lemma degree_subspace: "poly_vs.subspace {x. degree x n}"
  by (auto simp: poly_vs.subspace_def degree_add_le)

lemma monom_span: 
  "poly_vs.span {monom 1 x | x. x p} = {(x::'a::field poly). degree x p}"
(is "?L = ?R")
proof
  show "?L ?R"
  proof
    fix x assume "x ?L"
    moreover have hfin: "finite {P. x {..p}. P = monom 1 x}"
      by auto
    ultimately have 
      "x range (λu. v{monom 1 x | x. x {..p}}. smult (u v) v)"
      by (simp add: poly_vs.span_finite)
    hence " u. x = (v{monom 1 x | x. x {..p}}. smult (u v) v)"
      by (auto simp: image_iff)
    then obtain u 
      where p': "x = (v{monom 1 x | x. x {..p}}. smult (u v) v)"
      by blast
    have "v. v {monom 1 x | x. x {..p}} ==> degree (smult (u v) v) p"
      by (auto simp add: degree_monom_eq)
    hence "degree x p" using hfin
      apply (subst p')
      apply (rule degree_sum_le)
      by auto
    thus "x {x. degree x p}" by force
  qed
next
  show "?R ?L"
  proof
    fix x assume "x ?R"
    hence "degree x p" by force
    hence "x = (ip. monom (coeff x i) i)"
      by (simp add: poly_as_sum_of_monoms')
    also have
      "... = (ip. smult (coeff x (degree (monom (1::'a) i))) (monom 1 i))"
      by (auto simp add: smult_monom degree_monom_eq)
    also have
      "... = (v{monom 1 x | x. x {..p}}. smult ((λv. coeff x (degree v)) v) v)"
    proof (rule sum.reindex_cong)
      show "inj_on degree {monom (1::'a) x |x. x {..p}}"
      proof
        fix x 
        assume "x {monom (1::'a) x |x. x {..p}}" 
        hence " a. x = monom 1 a" by blast
        then obtain a where hx: "x = monom 1 a" by blast
        fix y 
        assume "y {monom (1::'a) x |x. x {..p}}" 
        hence " b. y = monom 1 b" by blast
        then obtain b where hy: "y = monom 1 b" by blast
        assume "degree x = degree y"
        thus "x = y" using hx hy by (simp add: degree_monom_eq)
      qed
      show "{..p} = degree ` {monom (1::'a) x |x. x {..p}}"
      proof
        show "{..p} degree ` {monom (1::'a) x |x. x {..p}}"
        proof
          fix x assume "x {..p}"
          hence "monom (1::'a) x {monom 1 x |x. x {..p}}" by force
          moreover have "degree (monom (1::'a) x) = x"
            by (simp add: degree_monom_eq)
          ultimately show "x degree ` {monom (1::'a) x |x. x {..p}}" by auto
        qed
        show "degree ` {monom (1::'a) x |x. x {..p}} {..p}"
          by (auto simp add: degree_monom_eq)
      qed
    next
      fix y assume "y {monom (1::'a) x |x. x {..p}}"
      hence "z {..p}. y = monom (1::'a) z" by blast
      then obtain z where "y = monom (1::'a) z" by blast
      thus 
        "smult (coeff x (degree (monom (1::'a) (degree y)))) (monom (1::'a) (degree y)) =
         smult (coeff x (degree y)) y"
        by (simp add: smult_monom degree_monom_eq)
    qed
    finally have "x = (v{monom 1 x | x. x {..p}}.
                      smult ((λv. coeff x (degree v)) v) v)" .
    thus "x ?L" by (auto simp add: poly_vs.span_finite)
  qed
qed

lemma monom_independent: 
  "poly_vs.independent {monom (1::'a::field) x | x. x p}"
proof (rule poly_vs.independent_if_scalars_zero)
  fix f::"'a poly ==> 'a"
  assume h: "(x{monom 1 x |x. x p}. smult (f x) x) = 0"
  have h': "(ip. monom (f (monom (1::'a) i)) i) =
            (x{monom (1::'a) x |x. x p}. smult (f x) x)"
  proof (rule sum.reindex_cong)
    show "inj_on degree {monom (1::'a) x |x. x p}"
      by (smt (verit) degree_monom_eq inj_on_def mem_Collect_eq zero_neq_one)
    show "{..p} = degree ` {monom (1::'a) x |x. x p}"
    proof
      show "{..p} degree ` {monom (1::'a) x |x. x p}"
      proof
        fix x assume "x {..p}"
        then have "x = degree (monom (1::'a) x) x p"
          by (auto simp: degree_monom_eq)
        thus "x degree ` {monom (1::'a) x |x. x p}" 
          by blast
      qed
      show "degree ` {monom (1::'a) x |x. x p} {..p}"
        by (force simp: degree_monom_eq)
    qed
  qed (auto simp: degree_monom_eq smult_monom)

  fix x::"'a poly"
  assume "x {monom 1 x |x. x p}"
  then obtain y where "y p" and "x = monom 1 y" by blast
  hence "f x = coeff (x{monom 1 x |x. x p}. smult (f x) x) y"
    by (auto simp: coeff_sum h'[symmetric])
  thus "f x = 0"
    using h by auto
qed force

lemma dim_degree: "poly_vs.dim {x. degree x n} = n + 1"
  using poly_vs.dim_eq_card_independent[OF monom_independent]
  by (auto simp: monom_span[symmetric] card_image image_Collect[symmetric]
      inj_on_def monom_eq_iff')

lemma degree_div: 
  fixes p q::"('a::idom_divide) poly" 
  assumes "q dvd p"
  shows "degree (p div q) = degree p - degree q" using assms
  by (metis (no_types, lifting) add_diff_cancel_left' degree_0 degree_mult_eq 
      diff_add_zero diff_zero div_by_0 dvd_div_eq_0_iff dvd_mult_div_cancel)

lemma lead_coeff_div: 
  fixes p q::"('a::{idom_divide, inverse}) poly" 
  assumes "q dvd p"
  shows "lead_coeff (p div q) = lead_coeff p / lead_coeff q" using assms
  by (smt (z3) div_by_0 dvd_div_mult_self lead_coeff_mult leading_coeff_0_iff
      nonzero_mult_div_cancel_right)

lemma complex_poly_eq: 
  "r = map_poly of_real (map_poly Re r) + smult i (map_poly of_real (map_poly Im r))"
  by (auto simp: poly_eq_iff coeff_map_poly complex_eq)

lemma complex_poly_cong: 
  "(map_poly Re p = map_poly Re q map_poly Im p = map_poly Im q) = (p = q)" 
  by (metis complex_poly_eq)

lemma map_poly_Im_of_real: "map_poly Im (map_poly of_real p) = 0"
  by (auto simp: poly_eq_iff coeff_map_poly)

lemma mult_map_poly_imp_map_poly: 
  assumes "map_poly complex_of_real q = r * map_poly complex_of_real p" 
          "p 0"
  shows "r = map_poly complex_of_real (map_poly Re r)"
proof -
  have h: "Im (*) i complex_of_real = id" by fastforce
  have "map_poly complex_of_real q = r * map_poly complex_of_real p" 
    using assms by blast
  also have "... = (map_poly of_real (map_poly Re r) +
                    smult i (map_poly of_real (map_poly Im r))) *
                   map_poly complex_of_real p"
    using complex_poly_eq by fastforce
  also have "... = map_poly of_real (map_poly Re r * p) +
                   smult i (map_poly of_real (map_poly Im r * p))"
    by (simp add: mult_poly_add_left)
  finally have "map_poly complex_of_real q =
                map_poly of_real (map_poly Re r * p) +
                smult i (map_poly of_real (map_poly Im r * p))" .
  hence "0 = map_poly Im (map_poly of_real (map_poly Re r * p) +
             smult i (map_poly of_real (map_poly Im r * p)))"
    by (auto simp: complex_poly_cong[symmetric] map_poly_Im_of_real)
  also have "... = map_poly of_real (map_poly Im r * p)"
    apply (rule poly_eqI)
    by (auto simp: coeff_map_poly coeff_mult)
  finally have "0 = map_poly complex_of_real (map_poly Im r) *
                    map_poly complex_of_real p" 
    by auto
  hence "map_poly complex_of_real (map_poly Im r) = 0" using assms by fastforce
  thus ?thesis apply (subst complex_poly_eq) by auto
qed

lemma map_poly_dvd: 
  fixes p q::"real poly"
  assumes hdvd: "map_poly complex_of_real p dvd
                    map_poly complex_of_real q" "q 0"
  shows "p dvd q" 
proof -
  from hdvd obtain r 
    where h:"map_poly complex_of_real q = r * map_poly complex_of_real p"
    by fastforce
  hence "r = map_poly complex_of_real (map_poly Re r)" 
    using mult_map_poly_imp_map_poly assms by force
  hence "map_poly complex_of_real q = map_poly complex_of_real (p * map_poly Re r)" 
    using h by auto
  hence "q = p * map_poly Re r" using of_real_poly_eq_iff by blast
  thus "p dvd q" by force
qed

lemma div_poly_eq_0: 
  fixes p q::"('a::idom_divide) poly" 
  assumes "q dvd p" "poly (p div q) x = 0" "q 0"
  shows "poly p x = 0"
  using assms by fastforce

lemma poly_map_poly_of_real_cnj: 
    "poly (map_poly of_real p) (cnj z) = cnj (poly (map_poly of_real p) z)"
  apply (induction p)
  by auto

text 
  induction rule on real polynomials, if $P \neq 0$ then either $(X-x)|P$ or
 (X-z)(X-cnj z)|P$, we induct by dividing by these polynomials.
 

lemma real_poly_roots_induct: 
  fixes P::"real poly ==> bool" and p::"real poly"
  assumes IH_real: "p x. P p ==> P (p * [:-x, 1:])"
      and IH_complex: "p a b. b 0 ==> P p
              ==> P (p * [: a*a + b*b, -2*a, 1 :])"
      and H0: "a. P [:a:]"
  defines "d degree p"
  shows "P p"
  using d_def
proof (induction d arbitrary: p rule: less_induct)
  fix p::"real poly"
  assume IH: "(q. degree q < degree p ==> P q)"
  show "P p"
  proof (cases "0 = degree p")
    fix p::"real poly" assume "0 = degree p"
    hence " a. p = [:a:]"
      by (simp add: degree_0_iff)
    thus "P p" using H0 by blast
  next
    assume hdeg: "0 degree p" 
    hence "¬ constant (poly (map_poly of_real p))"
      by (metis (no_types, opaque_lifting) constant_def constant_degree of_real_eq_iff of_real_poly_map_poly)
    then obtain z::complex where h: "poly (map_poly of_real p) z = 0" 
      using fundamental_theorem_of_algebra by blast
    show "P p"
    proof cases
      assume "Im z = 0"
      hence "z = Re z" by (simp add: complex_is_Real_iff)
      moreover have "[:-z, 1:] dvd map_poly of_real p" 
        using h poly_eq_0_iff_dvd by blast
      ultimately have "[:-(Re z), 1:] dvd p"
        by (smt (z3) dvd_iff_poly_eq_0 h of_real_0 of_real_eq_iff of_real_poly_map_poly)
      hence 2:"P (p div [:-Re z, 1:])"
        apply (subst IH)
        using hdeg by (auto simp: degree_div)
      moreover have 1:"p = (p div [:- Re z, 1:]) * [:-Re z, 1:]"
        by (metis [:- Re z, 1:] dvd p dvd_div_mult_self)
      ultimately show "P p"
        apply (subst 1)
        by (rule IH_real[OF 2])
    next
      assume "Im z 0"
      hence hcnj: "cnj z z" by (metis cnj.simps(2) neg_equal_zero)
      have h2: "poly (map_poly of_real p) (cnj z) = 0" 
        using h poly_map_poly_of_real_cnj by force
      have "[:-z, 1:] * [:-cnj z, 1:] dvd map_poly of_real p"
      proof (rule divides_mult)
        have "c. c dvd [:-z, 1:] ==> c dvd [:- cnj z, 1:] ==> is_unit c"
        proof -
          fix c
          assume h:"c dvd [:-z, 1:]" hence "degree c 1" using divides_degree by fastforce
          hence "degree c = 0 degree c = 1" by linarith
          thus "c dvd [:- cnj z, 1:] ==> is_unit c"
          proof
            assume "degree c = 0"
            moreover have "c 0" using h by fastforce
            ultimately show "is_unit c" by (simp add: is_unit_iff_degree)
          next
            assume hdeg: "degree c = 1"
            then obtain x where 1:"[:-z, 1:] = x*c" using h by fastforce
            hence "degree [:-z, 1:] = degree x + degree c"
              by (metis add.inverse_neutral degree_mult_eq mult_cancel_right
                  mult_poly_0_left pCons_eq_0_iff zero_neq_neg_one)
            hence "degree x = 0" using hdeg by auto
            then obtain x' where 2"x = [:x':]" using degree_0_iff by auto
            assume "c dvd [:-cnj z, 1:]"
            then obtain y where 3"[:-cnj z, 1:] = y*c" by fastforce
            hence "degree [:-cnj z, 1:] = degree y + degree c"
              by (metis add.inverse_neutral degree_mult_eq mult_cancel_right
                  mult_poly_0_left pCons_eq_0_iff zero_neq_neg_one)
            hence "degree y = 0" using hdeg by auto
            then obtain y' where 4"y = [:y':]" using degree_0_iff by auto
            moreover from hdeg obtain a b where 5:"c = [:a, b:]" and 6"b 0"
              by (meson degree_eq_oneE)
            from 1 2 5 6 have "x' = inverse b" by (auto simp: field_simps)
            moreover from 3 4 5 6 have "y' = inverse b" by (auto simp: field_simps)
            ultimately have "x = y" using 2 4 by presburger
            then have "z = cnj z" using 1 3 by (metis neg_equal_iff_equal pCons_eq_iff)
            thus "is_unit c" using hcnj by argo
          qed
        qed
        thus "coprime [:- z, 1:] [:- cnj z, 1:]" by (meson not_coprimeE)
        show "[:- z, 1:] dvd map_poly complex_of_real p"
          using h poly_eq_0_iff_dvd by auto
        show "[:- cnj z, 1:] dvd map_poly complex_of_real p"
          using h2 poly_eq_0_iff_dvd by blast
      qed
      moreover have "[:- z, 1:] * [:- cnj z, 1:] =
                     map_poly of_real [:Re z*Re z + Im z*Im z, -2*Re z, 1:]"
        by (auto simp: complex_eqI)
      ultimately have hdvd: 
        "map_poly complex_of_real [:Re z*Re z + Im z*Im z, -2*Re z, 1:] dvd
         map_poly complex_of_real p"
        by force
      hence "[:Re z*Re z + Im z*Im z, -2*Re z, 1:] dvd p" using map_poly_dvd 
        by blast
      hence 2:"P (p div [:Re z*Re z + Im z*Im z, -2*Re z, 1:])"
        apply (subst IH)
        using hdeg by (auto simp: degree_div)
      moreover have 1:
        "p = (p div [:Re z*Re z + Im z*Im z, -2*Re z, 1:]) *
                    [:Re z*Re z + Im z*Im z, -2*Re z, 1:]"
        apply (subst dvd_div_mult_self) 
        using [:Re z*Re z + Im z*Im z, -2*Re z, 1:] dvd p by auto
      ultimately show "P p"
        apply (subst 1)
        apply (rule IH_complex[of  "Im z" _ "Re z"])
        apply (meson Im z 0)
        by blast
    qed
  qed
qed

subsection The reciprocal polynomial

definition reciprocal_poly :: "nat ==> 'a::zero poly ==> 'a poly"
  where "reciprocal_poly p P =
          Poly (rev ((coeffs P) @ (replicate (p - degree P) 0)))"

lemma reciprocal_0: "reciprocal_poly p 0 = 0" by (simp add: reciprocal_poly_def)

lemma reciprocal_1: "reciprocal_poly p 1 = monom 1 p"
  by (simp add: reciprocal_poly_def monom_altdef Poly_append)

lemma coeff_reciprocal: 
  assumes hi: "i p" and hP: "degree P p"
  shows "coeff (reciprocal_poly p P) i = coeff P (p - i)"
proof cases
  assume "i < p - degree P"
  hence "degree P < p - i" using hP by linarith
  thus "coeff (reciprocal_poly p P) i = coeff P (p - i)"
    by (auto simp: reciprocal_poly_def nth_default_append coeff_eq_0)
next
  assume h: "¬i < p - degree P"
  show "coeff (reciprocal_poly p P) i = coeff P (p - i)"
  proof cases
    assume "P = 0"
    thus "coeff (reciprocal_poly p P) i = coeff P (p - i)" 
      by (simp add: reciprocal_0)
  next
    assume hP': "P 0"
    have "degree P p - i" using h hP by linarith
    moreover hence "(i - (p - degree P)) < length (rev (coeffs P))" 
      using hP' hP hi by (auto simp: length_coeffs)
    thus "coeff (reciprocal_poly p P) i = coeff P (p - i)"
      by (auto simp: reciprocal_poly_def nth_default_append coeff_eq_0 hP hP' 
          nth_default_nth rev_nth calculation coeffs_nth length_coeffs_degree)
  qed
qed

lemma coeff_reciprocal_less: 
  assumes hn: "p < i" and hP: "degree P p"
  shows "coeff (reciprocal_poly p P) i = 0"
proof cases
  assume "P = 0"
  thus ?thesis by (auto simp: reciprocal_0)
next
  assume "P 0"
  thus ?thesis
    using hn 
    by (auto simp: reciprocal_poly_def nth_default_append 
        nth_default_eq_dflt_iff hP length_coeffs)
qed

lemma reciprocal_monom: 
  assumes "n p"
  shows "reciprocal_poly p (monom a n) = monom a (p-n)"
proof (cases "a=0")
  case True
  then show ?thesis by (simp add: reciprocal_0)
next
  case False
  with np show ?thesis 
    apply (rule_tac poly_eqI)
    by (metis coeff_monom coeff_reciprocal coeff_reciprocal_less 
        diff_diff_cancel diff_le_self lead_coeff_monom not_le_imp_less)
qed

lemma reciprocal_degree: "reciprocal_poly (degree P) P = reflect_poly P"
  by (auto simp add: reciprocal_poly_def reflect_poly_def)

lemma degree_reciprocal:
  fixes P :: "('a::zero) poly" 
  assumes hP: "degree P p"
  shows "degree (reciprocal_poly p P) p"
proof (auto simp add: reciprocal_poly_def)
  have "degree (reciprocal_poly p P)
        length (replicate (p - degree P) (0::'a) @ rev (coeffs P))"
    by (metis degree_Poly reciprocal_poly_def rev_append rev_replicate)
  thus "degree (Poly (replicate (p - degree P) 0 @ rev (coeffs P))) p" 
    by (smt Suc_le_mono add_Suc_right coeffs_Poly degree_0 hP le_SucE le_SucI 
        le_add_diff_inverse2 le_zero_eq length_append length_coeffs_degree
        length_replicate length_rev length_strip_while_le reciprocal_0
        reciprocal_poly_def rev_append rev_replicate)
qed

lemma reciprocal_0_iff: 
  assumes hP: "degree P p" 
  shows "(reciprocal_poly p P = 0) = (P = 0)"
proof
  assume h: "reciprocal_poly p P = 0"
  show "P = 0"
  proof (rule poly_eqI)
    fix n
    show "coeff P n = coeff 0 n"
    proof cases
      assume hn: "n p"
      hence "p - n p" by auto
      hence "coeff (reciprocal_poly p P) (p - n) = coeff P n" 
        using hP hn by (auto simp: coeff_reciprocal)
      thus ?thesis using h by auto
    next
      assume hn: "¬ n p"
      thus ?thesis using hP by (metis coeff_0 dual_order.trans le_degree)
    qed
  qed
next
  assume "P = 0"
  thus "reciprocal_poly p P = 0" using reciprocal_0 by fast
qed

lemma poly_reciprocal: 
  fixes P::"'a::field poly"
  assumes hp: "degree P p" and hx: "x 0"
  shows "poly (reciprocal_poly p P) x = x^p * (poly P (inverse x))"
proof -
  have "poly (reciprocal_poly p P) x
      = poly ((Poly ((replicate (p - degree P) 0) @ rev (coeffs P)))) x"
    by (auto simp add: hx reflect_poly_def reciprocal_poly_def)
  also have "... = poly ((monom 1 (p - degree P)) * (reflect_poly P)) x"
    by (auto simp add: reflect_poly_def Poly_append)
  also have "... = x^(p - degree P) * x ^ degree P * poly P (inverse x)"
    by (auto simp add: poly_reflect_poly_nz poly_monom hx)
  also have "... = x^p * poly P (inverse x)"
    by (auto simp add: hp power_add[symmetric])
  finally show ?thesis .
qed

lemma reciprocal_fcompose: 
  fixes P::"('a::{ring_char_0,field}) poly" 
  assumes hP: "degree P p"
  shows "reciprocal_poly p P = monom 1 (p - degree P) * fcompose P 1 [:0, 1:]"
proof (rule poly_eq_by_eval, cases)
  fix x::'a
  assume hx: "x = 0"
  hence "poly (reciprocal_poly p P) x = coeff P p"
    using hP by (auto simp: poly_0_coeff_0 coeff_reciprocal)
  moreover have "poly (monom 1 (p - degree P)
    * fcompose P 1 [:0, 1:]) x = coeff P p"
  proof cases
    assume "degree P = p"
    thus ?thesis
      apply (induction P arbitrary: p)
      using hx by (auto simp: poly_monom degree_0_iff fcompose_pCons)
  next
    assume "degree P p"
    hence "degree P < p" using hP by auto
    thus ?thesis
      using hx by (auto simp: poly_monom coeff_eq_0)
  qed
  ultimately show "poly (reciprocal_poly p P) x = poly (monom 1 (p - degree P) * fcompose P 1 [:0, 1:]) x"
    by presburger
next
  fix x::'a assume "x 0"
  thus "poly (reciprocal_poly p P) x =
        poly (monom 1 (p - degree P) * fcompose P 1 [:0, 1:]) x"
    using hP 
    by (auto simp: poly_reciprocal poly_fcompose inverse_eq_divide
        poly_monom power_diff)
qed

lemma reciprocal_reciprocal: 
  fixes P :: "'a::{field,ring_char_0} poly"
  assumes hP: "degree P p"
  shows "reciprocal_poly p (reciprocal_poly p P) = P"
proof (rule poly_eq_by_eval)
  fix x
  show "poly (reciprocal_poly p (reciprocal_poly p P)) x = poly P x"
  proof cases
    assume "x = 0"
    thus "poly (reciprocal_poly p (reciprocal_poly p P)) x = poly P x" 
      using hP
      by (auto simp: poly_0_coeff_0 coeff_reciprocal degree_reciprocal)
  next
    assume hx: "x 0"
    hence "poly (reciprocal_poly p (reciprocal_poly p P)) x
        = x ^ p * (inverse x ^ p * poly P x)" using hP
      by (auto simp: poly_reciprocal degree_reciprocal)
    thus "poly (reciprocal_poly p (reciprocal_poly p P)) x = poly P x" 
      using hP hx left_right_inverse_power right_inverse by auto
  qed
qed

lemma reciprocal_smult: 
  fixes P :: "'a::idom poly" 
  assumes h: "degree P p"
  shows "reciprocal_poly p (smult n P) = smult n (reciprocal_poly p P)"
proof cases
  assume "n = 0"
  thus ?thesis by (auto simp add: reciprocal_poly_def)
next
  assume "n 0"
  thus ?thesis 
    by (auto simp add: reciprocal_poly_def smult_Poly coeffs_smult 
        rev_map[symmetric])
qed

lemma reciprocal_add: 
  fixes P Q :: "'a::comm_semiring_0 poly"
  assumes "degree P p" and "degree Q p" 
  shows "reciprocal_poly p (P + Q) = reciprocal_poly p P + reciprocal_poly p Q" 
(is "?L = ?R")
proof (rule poly_eqI, cases)
  fix n
  assume "n p"
  then show "coeff ?L n = coeff ?R n"
    using assms by (auto simp: degree_add_le coeff_reciprocal)
next
  fix n assume "¬n p"
  then show "coeff ?L n = coeff ?R n"
    using assms by (auto simp: degree_add_le coeff_reciprocal_less)
qed 

lemma reciprocal_diff: 
  fixes P Q :: "'a::comm_ring poly"
  assumes "degree P p" and "degree Q p" 
  shows "reciprocal_poly p (P - Q) = reciprocal_poly p P - reciprocal_poly p Q"
  by (metis (no_types, lifting) ab_group_add_class.ab_diff_conv_add_uminus assms
      add_diff_cancel degree_add_le degree_minus diff_add_cancel reciprocal_add)

lemma reciprocal_sum: 
  fixes P :: "'a ==> 'b::comm_semiring_0 poly" 
  assumes hP: "k. degree (P k) p"
  shows "reciprocal_poly p (kA. P k) = (kA. reciprocal_poly p (P k))"
proof (induct A rule: infinite_finite_induct)
  case (infinite A)
  then show ?case by (simp add: reciprocal_0)
next
  case empty
  then show ?case by (simp add: reciprocal_0)
next
  case (insert x F)
  assume "x F"
     and "reciprocal_poly p (sum P F) = (kF. reciprocal_poly p (P k))"
     and "finite F"
  moreover hence "reciprocal_poly p (sum P (insert x F))
      = reciprocal_poly p (P x) + reciprocal_poly p (sum P F)"
    by (auto simp add: reciprocal_add hP degree_sum_le)
  ultimately show "reciprocal_poly p (sum P (insert x F))
      = (kinsert x F. reciprocal_poly p (P k))"
    by (auto simp: Groups_Big.comm_monoid_add_class.sum.insert_if)
qed

lemma reciprocal_mult: 
  fixes P Q::"'a::{ring_char_0,field} poly" 
  assumes "degree (P * Q) p"
    and "degree P p" and "degree Q p"
  shows "monom 1 p * reciprocal_poly p (P * Q) =
         reciprocal_poly p P * reciprocal_poly p Q"
proof (cases "P=0 Q=0")
  case True
  then show ?thesis using assms(1
    by (auto simp: reciprocal_fcompose fcompose_mult)
next
  case False
  then show ?thesis  
    using assms
    by (auto simp: degree_mult_eq mult_monom reciprocal_fcompose fcompose_mult)
qed

lemma reciprocal_reflect_poly: 
  fixes P::"'a::{ring_char_0,field} poly" 
  assumes hP: "degree P p"
  shows "reciprocal_poly p P = monom 1 (p - degree P) * reflect_poly P"
proof (rule poly_eqI)
  fix n
  show "coeff (reciprocal_poly p P) n =
    coeff (monom 1 (p - degree P) * reflect_poly P) n"
  proof cases
    assume "n p" 
    thus ?thesis using hP
      by (auto simp: coeff_reciprocal coeff_monom_mult coeff_reflect_poly coeff_eq_0)
  next
    assume "¬ n p"
    thus ?thesis using hP
      by (auto simp: coeff_reciprocal_less coeff_monom_mult coeff_reflect_poly)
  qed
qed

lemma map_poly_reciprocal: 
  assumes "degree P p" and "f 0 = 0" 
  shows "map_poly f (reciprocal_poly p P) = reciprocal_poly p (map_poly f P)"
proof (rule poly_eqI)
  fix n 
  show "coeff (map_poly f (reciprocal_poly p P)) n =
         coeff (reciprocal_poly p (map_poly f P)) n"
  proof (cases "np")
    case True
    then show ?thesis 
      apply (subst coeff_reciprocal[OF True])
      subgoal by (meson assms(1) assms(2) degree_map_poly_le le_trans)
      by (simp add: assms(1) assms(2) coeff_map_poly coeff_reciprocal)
  next
    case False
    then show ?thesis 
      by (metis assms(1) assms(2) coeff_map_poly coeff_reciprocal_less 
          degree_map_poly_le dual_order.trans leI)
  qed
qed

subsection More about @{term proots_count}

lemma proots_count_monom: 
  assumes "0 A" 
  shows "proots_count (monom 1 d) A = 0"
  using assms by (auto simp: proots_count_def poly_monom)

lemma proots_count_reciprocal: 
  fixes P::"'a::{ring_char_0,field} poly"
  assumes hP: "degree P p" and h0: "P 0" and h0': "0 A"
  shows "proots_count (reciprocal_poly p P) A = proots_count P {x. inverse x A}"
proof -
  have "proots_count (reciprocal_poly p P) A =
        proots_count (fcompose P 1 [:0, 1:]) A"
    apply (subst reciprocal_fcompose[OF hP], subst proots_count_times)
    subgoal using h0 by (metis hP reciprocal_0_iff reciprocal_fcompose)
    subgoal using h0' by (auto simp: proots_count_monom)
    done

  also have "... = proots_count P {x. inverse x A}"
  proof (rule proots_fcompose_bij_eq[symmetric])
    show "bij_betw (λx. poly 1 x / poly [:0, 1:] x) A {x. inverse x A}"
    proof (rule bij_betw_imageI)
      show "inj_on (λx. poly 1 x / poly [:0, 1:] x) A"
        by (simp add: inj_on_def)

      show "(λx. poly 1 x / poly [:0, 1:] x) ` A = {x. inverse x A}"
      proof
        show "(λx. poly 1 x / poly [:0, 1:] x) ` A {x. inverse x A}"
          by force
        show "{x. inverse x A} (λx. poly 1 x / poly [:0, 1:] x) ` A"
        proof
          fix x assume "x {x::'a. inverse x A}"
          hence "x = poly 1 (inverse x) / poly [:0, 1:] (inverse x) inverse x A"
            by (auto simp: inverse_eq_divide)
          thus "x (λx. poly 1 x / poly [:0, 1:] x) ` A" by blast
        qed
      qed
    qed
  next
    show "c. 1 smult c [:0, 1:]" 
      by (metis coeff_pCons_0 degree_1 lead_coeff_1 pCons_0_0 pcompose_0'
          pcompose_smult smult_0_right zero_neq_one)
  qed (auto simp: assms infinite_UNIV_char_0)
  finally show ?thesis by linarith
qed

lemma proots_count_reciprocal': 
  fixes P::"real poly"
  assumes hP: "degree P p" and h0: "P 0"
  shows "proots_count P {x. 0 < x x < 1} =
         proots_count (reciprocal_poly p P) {x. 1 < x}"
proof (subst proots_count_reciprocal)
  show "proots_count P {x. 0 < x x < 1} =
      proots_count P {x. inverse x Collect ((<) 1)}"
    apply (rule arg_cong[of _ _ "proots_count P"])
    using one_less_inverse_iff by fastforce
qed (use assms in auto)

lemma proots_count_pos: 
  assumes "proots_count P S > 0" 
  shows "x S. poly P x = 0"
proof (rule ccontr)
  assume "¬ (xS. poly P x = 0)"
  hence "x. x S ==> poly P x 0" by blast
  hence "x. x S ==> order x P = 0" using order_0I by blast
  hence "proots_count P S = 0" by (force simp: proots_count_def)
  thus False using assms by presburger
qed

lemma proots_count_of_root_set: 
  assumes "P 0" "R S" and "x. xR ==> poly P x = 0"
  shows "proots_count P S card R"
proof -
  have "card R card (proots_within P S)"
    apply (rule card_mono)
    subgoal using assms by auto
    subgoal using assms(2) assms(3by (auto simp: proots_within_def)
    done
  also have "... proots_count P S"
    by (rule card_proots_within_leq[OF assms(1)])
  finally show ?thesis .
qed

lemma proots_count_of_root: assumes "P 0" "xS" "poly P x = 0"
  shows "proots_count P S > 0"
  using proots_count_of_root_set[of P "{x}" S] assms by force

subsection More about @{term changes}

lemma changes_nonneg: "0 changes xs"
  apply (induction xs rule: changes.induct)
  by simp_all

lemma changes_replicate_0: shows "changes (replicate n 0) = 0"
  apply (induction n)
  by auto

lemma changes_append_replicate_0: "changes (xs @ replicate n 0) = changes xs"
proof (induction xs rule: changes.induct)
  case (2 uu)
  then show ?case
    apply (induction n)
    by auto
qed (auto simp: changes_replicate_0)

lemma changes_scale_Cons: 
  fixes xs:: "real list" assumes hs: "s > 0"
  shows "changes (s * x # xs) = changes (x # xs)"
  apply (induction xs rule: changes.induct)
  using assms by (auto simp: mult_less_0_iff zero_less_mult_iff)

lemma changes_scale: 
  fixes xs::"('a::linordered_idom) list"
  assumes hs: "i. i < n ==> s i > 0" and hn: "length xs n"
  shows "changes [s i * (nth_default 0 xs i). i [0..<n]] = changes xs"
using assms
proof (induction xs arbitrary: s n rule: changes.induct)
  case 1
  show ?case by (auto simp: map_replicate_const changes_replicate_0)
next
  case (2 uu)
  show ?case
  proof (cases n)
    case 0
    then show ?thesis by force
  next
    case (Suc m)
    hence "map (λi. s i * nth_default 0 [uu] i) [0..<n] = [s 0 * uu] @ replicate m 0"
    proof (induction m arbitrary: n)
      case (Suc m n)
      from Suc have "map (λi. s i * nth_default 0 [uu] i) [0..<Suc m] =
                     [s 0 * uu] @ replicate m 0"
        by meson
      hence "map (λi. s i * nth_default 0 [uu] i) [0..<n] =
             [s 0 * uu] @ replicate m 0 @ [0]"
        using Suc by auto
      also have "... = [s 0 * uu] @ replicate (Suc m) 0"
        by (simp add: replicate_append_same)
      finally show ?case .
    qed fastforce
    then show ?thesis
      by (metis changes.simps(2) changes_append_replicate_0)
  qed
next
  case (3 a b xs s n)
  obtain m where hn: "n = m + 2"
    using 3(5)
    by (metis add_2_eq_Suc' diff_diff_cancel diff_le_self length_Suc_conv 
        nat_arith.suc1 ordered_cancel_comm_monoid_diff_class.add_diff_inverse)
  hence h: 
    "map (λi. s i * nth_default 0 (a # b # xs) i) [0..<n] =
      s 0 * a # s 1 * b # map (λi.
      (λ i. s (i+2)) i * nth_default 0 (xs) i) [0..<m]"
    apply (induction m arbitrary: n)
    by auto
  consider (neg)"a*b<0" | (nil)"b=0" | (pos)"¬a*b<0 ¬b=0" by linarith
  then show ?case
  proof (cases)
    case neg
    hence 
      "changes (map (λi. s i * nth_default 0 (a # b # xs) i) [0..<n]) =
        1 + changes (s 1 * b # map (λi. (λ i. s (i+2)) i
                                        * nth_default 0 (xs) i) [0..<m])"
      apply (subst h)
      using 3(4)[of 03(4)[of 1] hn
      by (metis (no_types, lifting) changes.simps(3) mult_less_0_iff pos2
          mult_pos_pos one_less_numeral_iff semiring_norm(76) trans_less_add2)
    also have 
      "... = 1 + changes (map (λi. s (Suc i) * nth_default 0 (b # xs) i) [0..<Suc m])"
      apply (rule arg_cong[of _ _ "λ x. 1 + changes x"])
      apply (induction m)
      by auto
    also have "... = changes (a # b # xs)"
      apply (subst 3(1)[OF neg])
      using 3 neg hn by auto
    finally show ?thesis .
  next
    case nil
    hence "changes (map (λi. s i * nth_default 0 (a # b # xs) i) [0..<n]) =
           changes (s 0 * a # map (λi. (λ i. s (i+2)) i * nth_default 0 (xs) i) [0..<m])"
      apply (subst h)
      using 3(4)[of 03(4)[of 1] hn
      by auto
    also have 
      "... = changes (map
               (λi. s (if i = 0 then 0 else Suc i) * nth_default 0 (a # xs) i)
              [0..<Suc m])"
      apply (rule arg_cong[of _ _ "λ x. changes x"])
      apply (induction m)
      by auto
    also have "... = changes (a # b # xs)"
      apply (subst 3(2))
      using 3 nil hn by auto
    finally show ?thesis .
  next
    case pos
    hence "changes (map (λi. s i * nth_default 0 (a # b # xs) i) [0..<n]) =
           changes (s 1 * b # map (λi. (λ i. s (i+2)) i * nth_default 0 (xs) i) [0..<m])"
      apply (subst h)
      using 3(4)[of 03(4)[of 1] hn
      by (metis (no_types, lifting) changes.simps(3) divisors_zero 
          mult_less_0_iff nat_1_add_1 not_square_less_zero one_less_numeral_iff
          semiring_norm(76) trans_less_add2 zero_less_mult_pos zero_less_two)
    also have
      "... = changes (map (λi. s (Suc i) * nth_default 0 (b # xs) i) [0..<Suc m])"
      apply (rule arg_cong[of _ _ "λ x. changes x"])
      apply (induction m)
      by auto
    also have "... = changes (a # b # xs)"
      apply (subst 3(3))
      using 3 pos hn by auto
    finally show ?thesis .
  qed
qed

lemma changes_scale_const: fixes xs::"'a::linordered_idom list" 
  assumes hs: "s 0"
  shows "changes (map ((*) s) xs) = changes xs"
  apply (induction xs rule: changes.induct)
    apply (simp, force)
  using hs by (auto simp: mult_less_0_iff zero_less_mult_iff)

lemma changes_snoc: fixes xs::"'a::linordered_idom list" 
  shows "changes (xs @ [b, a]) = (if a * b < 0 then 1 + changes (xs @ [b])
         else if b = 0 then changes (xs @ [a]) else changes (xs @ [b]))"
  apply (induction xs rule: changes.induct)
  subgoal by (force simp: mult_less_0_iff)
  subgoal by (force simp: mult_less_0_iff)
  subgoal by force
  done

lemma changes_rev: fixes xs:: "'a::linordered_idom list" 
  shows "changes (rev xs) = changes xs"
  apply (induction xs rule: changes.induct)
  by (auto simp: changes_snoc)

lemma changes_rev_about: fixes xs:: "'a::linordered_idom list" 
  shows "changes (replicate (p - length xs) 0 @ rev xs) = changes xs"
proof (induction p)
  case (Suc p)
  then show ?case
  proof cases
    assume "¬Suc p length xs"
    hence "Suc p - length xs = Suc (p - length xs)" by linarith
    thus ?case using Suc.IH changes_rev by auto
  qed (auto simp: changes_rev)
qed (auto simp: changes_rev)

lemma changes_add_between: 
  assumes "a x" and "x b"
  shows "changes (as @ [a, b] @ bs) = changes (as @ [a, x, b] @ bs)"
proof (induction as rule: changes.induct)
  case 1
  then show ?case using assms 
    apply (induction bs)
    by (auto simp: mult_less_0_iff)
next
  case (2 c)
  then show ?case 
    apply (induction bs)
    using assms by (auto simp: mult_less_0_iff)
next
  case (3 y z as)
  then show ?case
    using assms by (auto simp: mult_less_0_iff)
qed

lemma changes_all_nonneg: assumes "i. nth_default 0 xs i 0" shows "changes xs = 0"
  using assms
proof (induction xs rule: changes.induct)
  case (3 x1 x2 xs)
  moreover assume "(i. 0 nth_default 0 (x1 # x2 # xs) i)"
  moreover hence "(i. 0 nth_default 0 (x1 # xs) i)" 
    and "(i. 0 nth_default 0 (x2 # xs) i)"
    and "x1 * x2 0"
  proof -
    fix i
    assume h:"(i. 0 nth_default 0 (x1 # x2 # xs) i)"
    show "0 nth_default 0 (x1 # xs) i"
    proof (cases i)
      case 0
      then show ?thesis using h[of 0by force
    next
      case (Suc nat)
      then show ?thesis using h[of "Suc (Suc nat)"by force
    qed
    show "0 nth_default 0 (x2 # xs) i" using h[of "Suc i"by simp
    show "x1*x2 0" using h[of 0] h[of 1by simp
  qed
  ultimately show ?case by auto
qed auto

lemma changes_pCons: "changes (coeffs (pCons 0 f)) = changes (coeffs f)"
  by (auto simp: cCons_def)

lemma changes_increasing: 
  assumes "i. i < length xs - 1 ==> xs ! (i + 1) xs ! i" 
    and "length xs > 1"
    and "hd xs < 0" 
    and "last xs > 0"
  shows "changes xs = 1"
  using assms
proof (induction xs rule:changes.induct)
  case (3 x y xs)
  consider (neg)"x*y<0" | (nil)"y=0" | (pos)"¬x*y<0 ¬y=0" by linarith
  then show ?case
  proof cases
    case neg
    have "changes (y # xs) = 0"
    proof (rule changes_all_nonneg)
      fix i
      show "0 nth_default 0 (y # xs) i"
      proof (cases "i < length (y # xs)")
        case True
        then show ?thesis using 3(4)[of i] 
          apply (induction i)
          subgoal using 3(6) neg by (fastforce simp: mult_less_0_iff)
          subgoal using 3(4by (auto simp: nth_default_def)
          done
      next
        case False
        then show ?thesis by (simp add: nth_default_def)
      qed
    qed
    thus "changes (x # y # xs) = 1"
      using neg by force
  next
    case nil
    hence "xs []" using 3(7by force
    have h: "i. i < length (x # xs) - 1 ==> (x # xs) ! i (x # xs) ! (i + 1)"
    proof -
      fix i assume "i < length (x # xs) - 1"
      thus "(x # xs) ! i (x # xs) ! (i + 1)"
        apply (cases "i = 0")
        subgoal using 3(4)[of 03(4)[of 1xs [] by force
        using 3(4)[of "i+1"by simp
    qed
    have "changes (x # xs) = 1"
      apply (rule 3(2))
      using nil h xs [] 3(63(7by auto
    thus ?thesis
      using nil by force
  next
    case pos
    hence "xs []" using 3(63(7by (fastforce simp: mult_less_0_iff)
    have "changes (y # xs) = 1"
    proof (rule 3(3))
      show "¬ x * y < 0" "y 0"
        using pos by auto
      show "i. i < length (y # xs) - 1
        ==> (y # xs) ! i (y # xs) ! (i + 1)"
        using 3(4by force
      show "1 < length (y # xs)"
        using xs [] by force
      show "hd (y # xs) < 0"
        using 3(6) pos by (force simp: mult_less_0_iff)
      show "0 < last (y # xs)"
        using 3(7by force
    qed
    thus ?thesis using pos by auto
  qed
qed auto

end

Messung V0.5 in Prozent
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.18 Sekunden  ¤

*© 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.