| 
64785
 | 
     1  | 
(*  Title:      HOL/Euclidean_Division.thy
  | 
| 
 | 
     2  | 
    Author:     Manuel Eberl, TU Muenchen
  | 
| 
 | 
     3  | 
    Author:     Florian Haftmann, TU Muenchen
  | 
| 
 | 
     4  | 
*)
  | 
| 
 | 
     5  | 
  | 
| 
 | 
     6  | 
section \<open>Uniquely determined division in euclidean (semi)rings\<close>
  | 
| 
 | 
     7  | 
  | 
| 
 | 
     8  | 
theory Euclidean_Division
  | 
| 
 | 
     9  | 
  imports Nat_Transfer
  | 
| 
 | 
    10  | 
begin
  | 
| 
 | 
    11  | 
  | 
| 
 | 
    12  | 
subsection \<open>Quotient and remainder in integral domains\<close>
  | 
| 
 | 
    13  | 
  | 
| 
 | 
    14  | 
class semidom_modulo = algebraic_semidom + semiring_modulo
  | 
| 
 | 
    15  | 
begin
  | 
| 
 | 
    16  | 
  | 
| 
 | 
    17  | 
lemma mod_0 [simp]: "0 mod a = 0"
  | 
| 
 | 
    18  | 
  using div_mult_mod_eq [of 0 a] by simp
  | 
| 
 | 
    19  | 
  | 
| 
 | 
    20  | 
lemma mod_by_0 [simp]: "a mod 0 = a"
  | 
| 
 | 
    21  | 
  using div_mult_mod_eq [of a 0] by simp
  | 
| 
 | 
    22  | 
  | 
| 
 | 
    23  | 
lemma mod_by_1 [simp]:
  | 
| 
 | 
    24  | 
  "a mod 1 = 0"
  | 
| 
 | 
    25  | 
proof -
  | 
| 
 | 
    26  | 
  from div_mult_mod_eq [of a one] div_by_1 have "a + a mod 1 = a" by simp
  | 
| 
 | 
    27  | 
  then have "a + a mod 1 = a + 0" by simp
  | 
| 
 | 
    28  | 
  then show ?thesis by (rule add_left_imp_eq)
  | 
| 
 | 
    29  | 
qed
  | 
| 
 | 
    30  | 
  | 
| 
 | 
    31  | 
lemma mod_self [simp]:
  | 
| 
 | 
    32  | 
  "a mod a = 0"
  | 
| 
 | 
    33  | 
  using div_mult_mod_eq [of a a] by simp
  | 
| 
 | 
    34  | 
  | 
| 
 | 
    35  | 
lemma dvd_imp_mod_0 [simp]:
  | 
| 
 | 
    36  | 
  assumes "a dvd b"
  | 
| 
 | 
    37  | 
  shows "b mod a = 0"
  | 
| 
 | 
    38  | 
  using assms minus_div_mult_eq_mod [of b a] by simp
  | 
| 
 | 
    39  | 
  | 
| 
 | 
    40  | 
lemma mod_0_imp_dvd: 
  | 
| 
 | 
    41  | 
  assumes "a mod b = 0"
  | 
| 
 | 
    42  | 
  shows   "b dvd a"
  | 
| 
 | 
    43  | 
proof -
  | 
| 
 | 
    44  | 
  have "b dvd ((a div b) * b)" by simp
  | 
| 
 | 
    45  | 
  also have "(a div b) * b = a"
  | 
| 
 | 
    46  | 
    using div_mult_mod_eq [of a b] by (simp add: assms)
  | 
| 
 | 
    47  | 
  finally show ?thesis .
  | 
| 
 | 
    48  | 
qed
  | 
| 
 | 
    49  | 
  | 
| 
 | 
    50  | 
lemma mod_eq_0_iff_dvd:
  | 
| 
 | 
    51  | 
  "a mod b = 0 \<longleftrightarrow> b dvd a"
  | 
| 
 | 
    52  | 
  by (auto intro: mod_0_imp_dvd)
  | 
| 
 | 
    53  | 
  | 
| 
 | 
    54  | 
lemma dvd_eq_mod_eq_0 [nitpick_unfold, code]:
  | 
| 
 | 
    55  | 
  "a dvd b \<longleftrightarrow> b mod a = 0"
  | 
| 
 | 
    56  | 
  by (simp add: mod_eq_0_iff_dvd)
  | 
| 
 | 
    57  | 
  | 
| 
 | 
    58  | 
lemma dvd_mod_iff: 
  | 
| 
 | 
    59  | 
  assumes "c dvd b"
  | 
| 
 | 
    60  | 
  shows "c dvd a mod b \<longleftrightarrow> c dvd a"
  | 
| 
 | 
    61  | 
proof -
  | 
| 
 | 
    62  | 
  from assms have "(c dvd a mod b) \<longleftrightarrow> (c dvd ((a div b) * b + a mod b))" 
  | 
| 
 | 
    63  | 
    by (simp add: dvd_add_right_iff)
  | 
| 
 | 
    64  | 
  also have "(a div b) * b + a mod b = a"
  | 
| 
 | 
    65  | 
    using div_mult_mod_eq [of a b] by simp
  | 
| 
 | 
    66  | 
  finally show ?thesis .
  | 
| 
 | 
    67  | 
qed
  | 
| 
 | 
    68  | 
  | 
| 
 | 
    69  | 
lemma dvd_mod_imp_dvd:
  | 
| 
 | 
    70  | 
  assumes "c dvd a mod b" and "c dvd b"
  | 
| 
 | 
    71  | 
  shows "c dvd a"
  | 
| 
 | 
    72  | 
  using assms dvd_mod_iff [of c b a] by simp
  | 
| 
 | 
    73  | 
  | 
| 
 | 
    74  | 
end
  | 
| 
 | 
    75  | 
  | 
| 
 | 
    76  | 
class idom_modulo = idom + semidom_modulo
  | 
| 
 | 
    77  | 
begin
  | 
| 
 | 
    78  | 
  | 
| 
 | 
    79  | 
subclass idom_divide ..
  | 
| 
 | 
    80  | 
  | 
| 
 | 
    81  | 
lemma div_diff [simp]:
  | 
| 
 | 
    82  | 
  "c dvd a \<Longrightarrow> c dvd b \<Longrightarrow> (a - b) div c = a div c - b div c"
  | 
| 
 | 
    83  | 
  using div_add [of _  _ "- b"] by (simp add: dvd_neg_div)
  | 
| 
 | 
    84  | 
  | 
| 
 | 
    85  | 
end
  | 
| 
 | 
    86  | 
  | 
| 
 | 
    87  | 
  
  | 
| 
 | 
    88  | 
subsection \<open>Euclidean (semi)rings with explicit division and remainder\<close>
  | 
| 
 | 
    89  | 
  
  | 
| 
 | 
    90  | 
class euclidean_semiring = semidom_modulo + normalization_semidom + 
  | 
| 
 | 
    91  | 
  fixes euclidean_size :: "'a \<Rightarrow> nat"
  | 
| 
 | 
    92  | 
  assumes size_0 [simp]: "euclidean_size 0 = 0"
  | 
| 
 | 
    93  | 
  assumes mod_size_less: 
  | 
| 
 | 
    94  | 
    "b \<noteq> 0 \<Longrightarrow> euclidean_size (a mod b) < euclidean_size b"
  | 
| 
 | 
    95  | 
  assumes size_mult_mono:
  | 
| 
 | 
    96  | 
    "b \<noteq> 0 \<Longrightarrow> euclidean_size a \<le> euclidean_size (a * b)"
  | 
| 
 | 
    97  | 
begin
  | 
| 
 | 
    98  | 
  | 
| 
 | 
    99  | 
lemma size_mult_mono': "b \<noteq> 0 \<Longrightarrow> euclidean_size a \<le> euclidean_size (b * a)"
  | 
| 
 | 
   100  | 
  by (subst mult.commute) (rule size_mult_mono)
  | 
| 
 | 
   101  | 
  | 
| 
 | 
   102  | 
lemma euclidean_size_normalize [simp]:
  | 
| 
 | 
   103  | 
  "euclidean_size (normalize a) = euclidean_size a"
  | 
| 
 | 
   104  | 
proof (cases "a = 0")
  | 
| 
 | 
   105  | 
  case True
  | 
| 
 | 
   106  | 
  then show ?thesis
  | 
| 
 | 
   107  | 
    by simp
  | 
| 
 | 
   108  | 
next
  | 
| 
 | 
   109  | 
  case [simp]: False
  | 
| 
 | 
   110  | 
  have "euclidean_size (normalize a) \<le> euclidean_size (normalize a * unit_factor a)"
  | 
| 
 | 
   111  | 
    by (rule size_mult_mono) simp
  | 
| 
 | 
   112  | 
  moreover have "euclidean_size a \<le> euclidean_size (a * (1 div unit_factor a))"
  | 
| 
 | 
   113  | 
    by (rule size_mult_mono) simp
  | 
| 
 | 
   114  | 
  ultimately show ?thesis
  | 
| 
 | 
   115  | 
    by simp
  | 
| 
 | 
   116  | 
qed
  | 
| 
 | 
   117  | 
  | 
| 
 | 
   118  | 
lemma dvd_euclidean_size_eq_imp_dvd:
  | 
| 
 | 
   119  | 
  assumes "a \<noteq> 0" and "euclidean_size a = euclidean_size b"
  | 
| 
 | 
   120  | 
    and "b dvd a" 
  | 
| 
 | 
   121  | 
  shows "a dvd b"
  | 
| 
 | 
   122  | 
proof (rule ccontr)
  | 
| 
 | 
   123  | 
  assume "\<not> a dvd b"
  | 
| 
 | 
   124  | 
  hence "b mod a \<noteq> 0" using mod_0_imp_dvd [of b a] by blast
  | 
| 
 | 
   125  | 
  then have "b mod a \<noteq> 0" by (simp add: mod_eq_0_iff_dvd)
  | 
| 
 | 
   126  | 
  from \<open>b dvd a\<close> have "b dvd b mod a" by (simp add: dvd_mod_iff)
  | 
| 
 | 
   127  | 
  then obtain c where "b mod a = b * c" unfolding dvd_def by blast
  | 
| 
 | 
   128  | 
    with \<open>b mod a \<noteq> 0\<close> have "c \<noteq> 0" by auto
  | 
| 
 | 
   129  | 
  with \<open>b mod a = b * c\<close> have "euclidean_size (b mod a) \<ge> euclidean_size b"
  | 
| 
 | 
   130  | 
    using size_mult_mono by force
  | 
| 
 | 
   131  | 
  moreover from \<open>\<not> a dvd b\<close> and \<open>a \<noteq> 0\<close>
  | 
| 
 | 
   132  | 
  have "euclidean_size (b mod a) < euclidean_size a"
  | 
| 
 | 
   133  | 
    using mod_size_less by blast
  | 
| 
 | 
   134  | 
  ultimately show False using \<open>euclidean_size a = euclidean_size b\<close>
  | 
| 
 | 
   135  | 
    by simp
  | 
| 
 | 
   136  | 
qed
  | 
| 
 | 
   137  | 
  | 
| 
 | 
   138  | 
lemma euclidean_size_times_unit:
  | 
| 
 | 
   139  | 
  assumes "is_unit a"
  | 
| 
 | 
   140  | 
  shows   "euclidean_size (a * b) = euclidean_size b"
  | 
| 
 | 
   141  | 
proof (rule antisym)
  | 
| 
 | 
   142  | 
  from assms have [simp]: "a \<noteq> 0" by auto
  | 
| 
 | 
   143  | 
  thus "euclidean_size (a * b) \<ge> euclidean_size b" by (rule size_mult_mono')
  | 
| 
 | 
   144  | 
  from assms have "is_unit (1 div a)" by simp
  | 
| 
 | 
   145  | 
  hence "1 div a \<noteq> 0" by (intro notI) simp_all
  | 
| 
 | 
   146  | 
  hence "euclidean_size (a * b) \<le> euclidean_size ((1 div a) * (a * b))"
  | 
| 
 | 
   147  | 
    by (rule size_mult_mono')
  | 
| 
 | 
   148  | 
  also from assms have "(1 div a) * (a * b) = b"
  | 
| 
 | 
   149  | 
    by (simp add: algebra_simps unit_div_mult_swap)
  | 
| 
 | 
   150  | 
  finally show "euclidean_size (a * b) \<le> euclidean_size b" .
  | 
| 
 | 
   151  | 
qed
  | 
| 
 | 
   152  | 
  | 
| 
 | 
   153  | 
lemma euclidean_size_unit:
  | 
| 
 | 
   154  | 
  "is_unit a \<Longrightarrow> euclidean_size a = euclidean_size 1"
  | 
| 
 | 
   155  | 
  using euclidean_size_times_unit [of a 1] by simp
  | 
| 
 | 
   156  | 
  | 
| 
 | 
   157  | 
lemma unit_iff_euclidean_size: 
  | 
| 
 | 
   158  | 
  "is_unit a \<longleftrightarrow> euclidean_size a = euclidean_size 1 \<and> a \<noteq> 0"
  | 
| 
 | 
   159  | 
proof safe
  | 
| 
 | 
   160  | 
  assume A: "a \<noteq> 0" and B: "euclidean_size a = euclidean_size 1"
  | 
| 
 | 
   161  | 
  show "is_unit a"
  | 
| 
 | 
   162  | 
    by (rule dvd_euclidean_size_eq_imp_dvd [OF A B]) simp_all
  | 
| 
 | 
   163  | 
qed (auto intro: euclidean_size_unit)
  | 
| 
 | 
   164  | 
  | 
| 
 | 
   165  | 
lemma euclidean_size_times_nonunit:
  | 
| 
 | 
   166  | 
  assumes "a \<noteq> 0" "b \<noteq> 0" "\<not> is_unit a"
  | 
| 
 | 
   167  | 
  shows   "euclidean_size b < euclidean_size (a * b)"
  | 
| 
 | 
   168  | 
proof (rule ccontr)
  | 
| 
 | 
   169  | 
  assume "\<not>euclidean_size b < euclidean_size (a * b)"
  | 
| 
 | 
   170  | 
  with size_mult_mono'[OF assms(1), of b] 
  | 
| 
 | 
   171  | 
    have eq: "euclidean_size (a * b) = euclidean_size b" by simp
  | 
| 
 | 
   172  | 
  have "a * b dvd b"
  | 
| 
 | 
   173  | 
    by (rule dvd_euclidean_size_eq_imp_dvd [OF _ eq]) (insert assms, simp_all)
  | 
| 
 | 
   174  | 
  hence "a * b dvd 1 * b" by simp
  | 
| 
 | 
   175  | 
  with \<open>b \<noteq> 0\<close> have "is_unit a" by (subst (asm) dvd_times_right_cancel_iff)
  | 
| 
 | 
   176  | 
  with assms(3) show False by contradiction
  | 
| 
 | 
   177  | 
qed
  | 
| 
 | 
   178  | 
  | 
| 
 | 
   179  | 
lemma dvd_imp_size_le:
  | 
| 
 | 
   180  | 
  assumes "a dvd b" "b \<noteq> 0" 
  | 
| 
 | 
   181  | 
  shows   "euclidean_size a \<le> euclidean_size b"
  | 
| 
 | 
   182  | 
  using assms by (auto elim!: dvdE simp: size_mult_mono)
  | 
| 
 | 
   183  | 
  | 
| 
 | 
   184  | 
lemma dvd_proper_imp_size_less:
  | 
| 
 | 
   185  | 
  assumes "a dvd b" "\<not> b dvd a" "b \<noteq> 0" 
  | 
| 
 | 
   186  | 
  shows   "euclidean_size a < euclidean_size b"
  | 
| 
 | 
   187  | 
proof -
  | 
| 
 | 
   188  | 
  from assms(1) obtain c where "b = a * c" by (erule dvdE)
  | 
| 
 | 
   189  | 
  hence z: "b = c * a" by (simp add: mult.commute)
  | 
| 
 | 
   190  | 
  from z assms have "\<not>is_unit c" by (auto simp: mult.commute mult_unit_dvd_iff)
  | 
| 
 | 
   191  | 
  with z assms show ?thesis
  | 
| 
 | 
   192  | 
    by (auto intro!: euclidean_size_times_nonunit)
  | 
| 
 | 
   193  | 
qed
  | 
| 
 | 
   194  | 
  | 
| 
 | 
   195  | 
end
  | 
| 
 | 
   196  | 
  | 
| 
 | 
   197  | 
class euclidean_ring = idom_modulo + euclidean_semiring
  | 
| 
 | 
   198  | 
  | 
| 
 | 
   199  | 
  
  | 
| 
 | 
   200  | 
subsection \<open>Uniquely determined division\<close>
  | 
| 
 | 
   201  | 
  
  | 
| 
 | 
   202  | 
class unique_euclidean_semiring = euclidean_semiring + 
  | 
| 
 | 
   203  | 
  fixes uniqueness_constraint :: "'a \<Rightarrow> 'a \<Rightarrow> bool"
  | 
| 
 | 
   204  | 
  assumes size_mono_mult:
  | 
| 
 | 
   205  | 
    "b \<noteq> 0 \<Longrightarrow> euclidean_size a < euclidean_size c
  | 
| 
 | 
   206  | 
      \<Longrightarrow> euclidean_size (a * b) < euclidean_size (c * b)"
  | 
| 
 | 
   207  | 
    -- \<open>FIXME justify\<close>
  | 
| 
 | 
   208  | 
  assumes uniqueness_constraint_mono_mult:
  | 
| 
 | 
   209  | 
    "uniqueness_constraint a b \<Longrightarrow> uniqueness_constraint (a * c) (b * c)"
  | 
| 
 | 
   210  | 
  assumes uniqueness_constraint_mod:
  | 
| 
 | 
   211  | 
    "b \<noteq> 0 \<Longrightarrow> \<not> b dvd a \<Longrightarrow> uniqueness_constraint (a mod b) b"
  | 
| 
 | 
   212  | 
  assumes div_bounded:
  | 
| 
 | 
   213  | 
    "b \<noteq> 0 \<Longrightarrow> uniqueness_constraint r b
  | 
| 
 | 
   214  | 
    \<Longrightarrow> euclidean_size r < euclidean_size b
  | 
| 
 | 
   215  | 
    \<Longrightarrow> (q * b + r) div b = q"
  | 
| 
 | 
   216  | 
begin
  | 
| 
 | 
   217  | 
  | 
| 
 | 
   218  | 
lemma divmod_cases [case_names divides remainder by0]:
  | 
| 
 | 
   219  | 
  obtains 
  | 
| 
 | 
   220  | 
    (divides) q where "b \<noteq> 0"
  | 
| 
 | 
   221  | 
      and "a div b = q"
  | 
| 
 | 
   222  | 
      and "a mod b = 0"
  | 
| 
 | 
   223  | 
      and "a = q * b"
  | 
| 
 | 
   224  | 
  | (remainder) q r where "b \<noteq> 0" and "r \<noteq> 0"
  | 
| 
 | 
   225  | 
      and "uniqueness_constraint r b"
  | 
| 
 | 
   226  | 
      and "euclidean_size r < euclidean_size b"
  | 
| 
 | 
   227  | 
      and "a div b = q"
  | 
| 
 | 
   228  | 
      and "a mod b = r"
  | 
| 
 | 
   229  | 
      and "a = q * b + r"
  | 
| 
 | 
   230  | 
  | (by0) "b = 0"
  | 
| 
 | 
   231  | 
proof (cases "b = 0")
  | 
| 
 | 
   232  | 
  case True
  | 
| 
 | 
   233  | 
  then show thesis
  | 
| 
 | 
   234  | 
  by (rule by0)
  | 
| 
 | 
   235  | 
next
  | 
| 
 | 
   236  | 
  case False
  | 
| 
 | 
   237  | 
  show thesis
  | 
| 
 | 
   238  | 
  proof (cases "b dvd a")
  | 
| 
 | 
   239  | 
    case True
  | 
| 
 | 
   240  | 
    then obtain q where "a = b * q" ..
  | 
| 
 | 
   241  | 
    with \<open>b \<noteq> 0\<close> divides
  | 
| 
 | 
   242  | 
    show thesis
  | 
| 
 | 
   243  | 
      by (simp add: ac_simps)
  | 
| 
 | 
   244  | 
  next
  | 
| 
 | 
   245  | 
    case False
  | 
| 
 | 
   246  | 
    then have "a mod b \<noteq> 0"
  | 
| 
 | 
   247  | 
      by (simp add: mod_eq_0_iff_dvd)
  | 
| 
 | 
   248  | 
    moreover from \<open>b \<noteq> 0\<close> \<open>\<not> b dvd a\<close> have "uniqueness_constraint (a mod b) b"
  | 
| 
 | 
   249  | 
      by (rule uniqueness_constraint_mod)
  | 
| 
 | 
   250  | 
    moreover have "euclidean_size (a mod b) < euclidean_size b"
  | 
| 
 | 
   251  | 
      using \<open>b \<noteq> 0\<close> by (rule mod_size_less)
  | 
| 
 | 
   252  | 
    moreover have "a = a div b * b + a mod b"
  | 
| 
 | 
   253  | 
      by (simp add: div_mult_mod_eq)
  | 
| 
 | 
   254  | 
    ultimately show thesis
  | 
| 
 | 
   255  | 
      using \<open>b \<noteq> 0\<close> by (blast intro: remainder)
  | 
| 
 | 
   256  | 
  qed
  | 
| 
 | 
   257  | 
qed
  | 
| 
 | 
   258  | 
  | 
| 
 | 
   259  | 
lemma div_eqI:
  | 
| 
 | 
   260  | 
  "a div b = q" if "b \<noteq> 0" "uniqueness_constraint r b"
  | 
| 
 | 
   261  | 
    "euclidean_size r < euclidean_size b" "q * b + r = a"
  | 
| 
 | 
   262  | 
proof -
  | 
| 
 | 
   263  | 
  from that have "(q * b + r) div b = q"
  | 
| 
 | 
   264  | 
    by (auto intro: div_bounded)
  | 
| 
 | 
   265  | 
  with that show ?thesis
  | 
| 
 | 
   266  | 
    by simp
  | 
| 
 | 
   267  | 
qed
  | 
| 
 | 
   268  | 
  | 
| 
 | 
   269  | 
lemma mod_eqI:
  | 
| 
 | 
   270  | 
  "a mod b = r" if "b \<noteq> 0" "uniqueness_constraint r b"
  | 
| 
 | 
   271  | 
    "euclidean_size r < euclidean_size b" "q * b + r = a" 
  | 
| 
 | 
   272  | 
proof -
  | 
| 
 | 
   273  | 
  from that have "a div b = q"
  | 
| 
 | 
   274  | 
    by (rule div_eqI)
  | 
| 
 | 
   275  | 
  moreover have "a div b * b + a mod b = a"
  | 
| 
 | 
   276  | 
    by (fact div_mult_mod_eq)
  | 
| 
 | 
   277  | 
  ultimately have "a div b * b + a mod b = a div b * b + r"
  | 
| 
 | 
   278  | 
    using \<open>q * b + r = a\<close> by simp
  | 
| 
 | 
   279  | 
  then show ?thesis
  | 
| 
 | 
   280  | 
    by simp
  | 
| 
 | 
   281  | 
qed
  | 
| 
 | 
   282  | 
  | 
| 
 | 
   283  | 
end
  | 
| 
 | 
   284  | 
  | 
| 
 | 
   285  | 
class unique_euclidean_ring = euclidean_ring + unique_euclidean_semiring
  | 
| 
 | 
   286  | 
  | 
| 
 | 
   287  | 
end
  |