src/HOL/Library/Polynomial_GCD_euclidean.thy
author haftmann
Wed, 17 Feb 2016 21:51:58 +0100
changeset 62352 35a9e1cbb5b3
permissions -rw-r--r--
separated potentially conflicting type class instance into separate theory
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
62352
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     1
(*  Title:      HOL/Library/Polynomial_GCD_euclidean.thy
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     2
    Author:     Brian Huffman
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     3
    Author:     Clemens Ballarin
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     4
    Author:     Amine Chaieb
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     5
    Author:     Florian Haftmann
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     6
*)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     7
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     8
section \<open>GCD and LCM on polynomials over a field\<close>
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
     9
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    10
theory Polynomial_GCD_euclidean
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    11
imports Main "~~/src/HOL/GCD" "~~/src/HOL/Library/Polynomial"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    12
begin
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    13
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    14
subsection \<open>GCD of polynomials\<close>
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    15
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    16
instantiation poly :: (field) gcd
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    17
begin
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    18
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    19
function gcd_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    20
where
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    21
  "gcd (x::'a poly) 0 = smult (inverse (coeff x (degree x))) x"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    22
| "y \<noteq> 0 \<Longrightarrow> gcd (x::'a poly) y = gcd y (x mod y)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    23
by auto
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    24
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    25
termination "gcd :: _ poly \<Rightarrow> _"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    26
by (relation "measure (\<lambda>(x, y). if y = 0 then 0 else Suc (degree y))")
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    27
   (auto dest: degree_mod_less)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    28
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    29
declare gcd_poly.simps [simp del]
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    30
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    31
definition lcm_poly :: "'a::field poly \<Rightarrow> 'a poly \<Rightarrow> 'a poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    32
where
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    33
  "lcm_poly a b = a * b div smult (coeff a (degree a) * coeff b (degree b)) (gcd a b)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    34
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    35
instance ..
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    36
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    37
end
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    38
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    39
lemma
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    40
  fixes x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    41
  shows poly_gcd_dvd1 [iff]: "gcd x y dvd x"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    42
    and poly_gcd_dvd2 [iff]: "gcd x y dvd y"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    43
  apply (induct x y rule: gcd_poly.induct)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    44
  apply (simp_all add: gcd_poly.simps)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    45
  apply (fastforce simp add: smult_dvd_iff dest: inverse_zero_imp_zero)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    46
  apply (blast dest: dvd_mod_imp_dvd)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    47
  done
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    48
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    49
lemma poly_gcd_greatest:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    50
  fixes k x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    51
  shows "k dvd x \<Longrightarrow> k dvd y \<Longrightarrow> k dvd gcd x y"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    52
  by (induct x y rule: gcd_poly.induct)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    53
     (simp_all add: gcd_poly.simps dvd_mod dvd_smult)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    54
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    55
lemma dvd_poly_gcd_iff [iff]:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    56
  fixes k x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    57
  shows "k dvd gcd x y \<longleftrightarrow> k dvd x \<and> k dvd y"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    58
  by (auto intro!: poly_gcd_greatest intro: dvd_trans [of _ "gcd x y"])
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    59
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    60
lemma poly_gcd_monic:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    61
  fixes x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    62
  shows "coeff (gcd x y) (degree (gcd x y)) =
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    63
    (if x = 0 \<and> y = 0 then 0 else 1)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    64
  by (induct x y rule: gcd_poly.induct)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    65
     (simp_all add: gcd_poly.simps nonzero_imp_inverse_nonzero)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    66
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    67
lemma poly_gcd_zero_iff [simp]:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    68
  fixes x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    69
  shows "gcd x y = 0 \<longleftrightarrow> x = 0 \<and> y = 0"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    70
  by (simp only: dvd_0_left_iff [symmetric] dvd_poly_gcd_iff)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    71
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    72
lemma poly_gcd_0_0 [simp]:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    73
  "gcd (0::_ poly) 0 = 0"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    74
  by simp
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    75
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    76
lemma poly_dvd_antisym:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    77
  fixes p q :: "'a::idom poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    78
  assumes coeff: "coeff p (degree p) = coeff q (degree q)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    79
  assumes dvd1: "p dvd q" and dvd2: "q dvd p" shows "p = q"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    80
proof (cases "p = 0")
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    81
  case True with coeff show "p = q" by simp
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    82
next
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    83
  case False with coeff have "q \<noteq> 0" by auto
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    84
  have degree: "degree p = degree q"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    85
    using \<open>p dvd q\<close> \<open>q dvd p\<close> \<open>p \<noteq> 0\<close> \<open>q \<noteq> 0\<close>
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    86
    by (intro order_antisym dvd_imp_degree_le)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    87
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    88
  from \<open>p dvd q\<close> obtain a where a: "q = p * a" ..
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    89
  with \<open>q \<noteq> 0\<close> have "a \<noteq> 0" by auto
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    90
  with degree a \<open>p \<noteq> 0\<close> have "degree a = 0"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    91
    by (simp add: degree_mult_eq)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    92
  with coeff a show "p = q"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    93
    by (cases a, auto split: if_splits)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    94
qed
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    95
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    96
lemma poly_gcd_unique:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    97
  fixes d x y :: "_ poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    98
  assumes dvd1: "d dvd x" and dvd2: "d dvd y"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
    99
    and greatest: "\<And>k. k dvd x \<Longrightarrow> k dvd y \<Longrightarrow> k dvd d"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   100
    and monic: "coeff d (degree d) = (if x = 0 \<and> y = 0 then 0 else 1)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   101
  shows "gcd x y = d"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   102
proof -
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   103
  have "coeff (gcd x y) (degree (gcd x y)) = coeff d (degree d)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   104
    by (simp_all add: poly_gcd_monic monic)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   105
  moreover have "gcd x y dvd d"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   106
    using poly_gcd_dvd1 poly_gcd_dvd2 by (rule greatest)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   107
  moreover have "d dvd gcd x y"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   108
    using dvd1 dvd2 by (rule poly_gcd_greatest)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   109
  ultimately show ?thesis
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   110
    by (rule poly_dvd_antisym)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   111
qed
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   112
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   113
instance poly :: (field) semiring_gcd
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   114
proof
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   115
  fix p q :: "'a::field poly"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   116
  show "normalize (gcd p q) = gcd p q"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   117
    by (induct p q rule: gcd_poly.induct)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   118
      (simp_all add: gcd_poly.simps normalize_poly_def)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   119
  show "lcm p q = normalize (p * q) div gcd p q"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   120
    by (simp add: coeff_degree_mult div_smult_left div_smult_right lcm_poly_def normalize_poly_def)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   121
      (metis (no_types, lifting) div_smult_right inverse_mult_distrib inverse_zero mult.commute pdivmod_rel pdivmod_rel_def smult_eq_0_iff)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   122
qed simp_all
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   123
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   124
lemma poly_gcd_1_left [simp]: "gcd 1 y = (1 :: _ poly)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   125
by (rule poly_gcd_unique) simp_all
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   126
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   127
lemma poly_gcd_1_right [simp]: "gcd x 1 = (1 :: _ poly)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   128
by (rule poly_gcd_unique) simp_all
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   129
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   130
lemma poly_gcd_minus_left [simp]: "gcd (- x) y = gcd x (y :: _ poly)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   131
by (rule poly_gcd_unique) (simp_all add: poly_gcd_monic)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   132
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   133
lemma poly_gcd_minus_right [simp]: "gcd x (- y) = gcd x (y :: _ poly)"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   134
by (rule poly_gcd_unique) (simp_all add: poly_gcd_monic)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   135
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   136
lemma poly_gcd_code [code]:
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   137
  "gcd x y = (if y = 0 then normalize x else gcd y (x mod (y :: _ poly)))"
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   138
  by (simp add: gcd_poly.simps)
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   139
35a9e1cbb5b3 separated potentially conflicting type class instance into separate theory
haftmann
parents:
diff changeset
   140
end