src/HOL/Divides.thy
changeset 61433 a4c0de1df3d8
parent 61275 053ec04ea866
child 61649 268d88ec9087
equal deleted inserted replaced
61432:1502f2410d8b 61433:a4c0de1df3d8
   811 end
   811 end
   812 
   812 
   813 
   813 
   814 subsection \<open>Division on @{typ nat}\<close>
   814 subsection \<open>Division on @{typ nat}\<close>
   815 
   815 
       
   816 context
       
   817 begin
       
   818 
   816 text \<open>
   819 text \<open>
   817   We define @{const divide} and @{const mod} on @{typ nat} by means
   820   We define @{const divide} and @{const mod} on @{typ nat} by means
   818   of a characteristic relation with two input arguments
   821   of a characteristic relation with two input arguments
   819   @{term "m::nat"}, @{term "n::nat"} and two output arguments
   822   @{term "m::nat"}, @{term "n::nat"} and two output arguments
   820   @{term "q::nat"}(uotient) and @{term "r::nat"}(emainder).
   823   @{term "q::nat"}(uotient) and @{term "r::nat"}(emainder).
   825     m = fst qr * n + snd qr \<and>
   828     m = fst qr * n + snd qr \<and>
   826       (if n = 0 then fst qr = 0 else if n > 0 then 0 \<le> snd qr \<and> snd qr < n else n < snd qr \<and> snd qr \<le> 0)"
   829       (if n = 0 then fst qr = 0 else if n > 0 then 0 \<le> snd qr \<and> snd qr < n else n < snd qr \<and> snd qr \<le> 0)"
   827 
   830 
   828 text \<open>@{const divmod_nat_rel} is total:\<close>
   831 text \<open>@{const divmod_nat_rel} is total:\<close>
   829 
   832 
   830 lemma divmod_nat_rel_ex:
   833 qualified lemma divmod_nat_rel_ex:
   831   obtains q r where "divmod_nat_rel m n (q, r)"
   834   obtains q r where "divmod_nat_rel m n (q, r)"
   832 proof (cases "n = 0")
   835 proof (cases "n = 0")
   833   case True  with that show thesis
   836   case True  with that show thesis
   834     by (auto simp add: divmod_nat_rel_def)
   837     by (auto simp add: divmod_nat_rel_def)
   835 next
   838 next
   858     using \<open>n \<noteq> 0\<close> by (auto simp add: divmod_nat_rel_def)
   861     using \<open>n \<noteq> 0\<close> by (auto simp add: divmod_nat_rel_def)
   859 qed
   862 qed
   860 
   863 
   861 text \<open>@{const divmod_nat_rel} is injective:\<close>
   864 text \<open>@{const divmod_nat_rel} is injective:\<close>
   862 
   865 
   863 lemma divmod_nat_rel_unique:
   866 qualified lemma divmod_nat_rel_unique:
   864   assumes "divmod_nat_rel m n qr"
   867   assumes "divmod_nat_rel m n qr"
   865     and "divmod_nat_rel m n qr'"
   868     and "divmod_nat_rel m n qr'"
   866   shows "qr = qr'"
   869   shows "qr = qr'"
   867 proof (cases "n = 0")
   870 proof (cases "n = 0")
   868   case True with assms show ?thesis
   871   case True with assms show ?thesis
   885 text \<open>
   888 text \<open>
   886   We instantiate divisibility on the natural numbers by
   889   We instantiate divisibility on the natural numbers by
   887   means of @{const divmod_nat_rel}:
   890   means of @{const divmod_nat_rel}:
   888 \<close>
   891 \<close>
   889 
   892 
   890 definition divmod_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat \<times> nat" where
   893 qualified definition divmod_nat :: "nat \<Rightarrow> nat \<Rightarrow> nat \<times> nat" where
   891   "divmod_nat m n = (THE qr. divmod_nat_rel m n qr)"
   894   "divmod_nat m n = (THE qr. divmod_nat_rel m n qr)"
   892 
   895 
   893 lemma divmod_nat_rel_divmod_nat:
   896 qualified lemma divmod_nat_rel_divmod_nat:
   894   "divmod_nat_rel m n (divmod_nat m n)"
   897   "divmod_nat_rel m n (divmod_nat m n)"
   895 proof -
   898 proof -
   896   from divmod_nat_rel_ex
   899   from divmod_nat_rel_ex
   897     obtain qr where rel: "divmod_nat_rel m n qr" .
   900     obtain qr where rel: "divmod_nat_rel m n qr" .
   898   then show ?thesis
   901   then show ?thesis
   899   by (auto simp add: divmod_nat_def intro: theI elim: divmod_nat_rel_unique)
   902   by (auto simp add: divmod_nat_def intro: theI elim: divmod_nat_rel_unique)
   900 qed
   903 qed
   901 
   904 
   902 lemma divmod_nat_unique:
   905 qualified lemma divmod_nat_unique:
   903   assumes "divmod_nat_rel m n qr"
   906   assumes "divmod_nat_rel m n qr"
   904   shows "divmod_nat m n = qr"
   907   shows "divmod_nat m n = qr"
   905   using assms by (auto intro: divmod_nat_rel_unique divmod_nat_rel_divmod_nat)
   908   using assms by (auto intro: divmod_nat_rel_unique divmod_nat_rel_divmod_nat)
   906 
   909 
       
   910 qualified lemma divmod_nat_zero: "divmod_nat m 0 = (0, m)"
       
   911   by (simp add: Divides.divmod_nat_unique divmod_nat_rel_def)
       
   912 
       
   913 qualified lemma divmod_nat_zero_left: "divmod_nat 0 n = (0, 0)"
       
   914   by (simp add: Divides.divmod_nat_unique divmod_nat_rel_def)
       
   915 
       
   916 qualified lemma divmod_nat_base: "m < n \<Longrightarrow> divmod_nat m n = (0, m)"
       
   917   by (simp add: divmod_nat_unique divmod_nat_rel_def)
       
   918 
       
   919 qualified lemma divmod_nat_step:
       
   920   assumes "0 < n" and "n \<le> m"
       
   921   shows "divmod_nat m n = apfst Suc (divmod_nat (m - n) n)"
       
   922 proof (rule divmod_nat_unique)
       
   923   have "divmod_nat_rel (m - n) n (divmod_nat (m - n) n)"
       
   924     by (fact divmod_nat_rel_divmod_nat)
       
   925   then show "divmod_nat_rel m n (apfst Suc (divmod_nat (m - n) n))"
       
   926     unfolding divmod_nat_rel_def using assms by auto
       
   927 qed
       
   928 
       
   929 end
       
   930   
   907 instantiation nat :: semiring_div
   931 instantiation nat :: semiring_div
   908 begin
   932 begin
   909 
   933 
   910 definition divide_nat where
   934 definition divide_nat where
   911   div_nat_def: "m div n = fst (divmod_nat m n)"
   935   div_nat_def: "m div n = fst (Divides.divmod_nat m n)"
   912 
   936 
   913 definition mod_nat where
   937 definition mod_nat where
   914   "m mod n = snd (divmod_nat m n)"
   938   "m mod n = snd (Divides.divmod_nat m n)"
   915 
   939 
   916 lemma fst_divmod_nat [simp]:
   940 lemma fst_divmod_nat [simp]:
   917   "fst (divmod_nat m n) = m div n"
   941   "fst (Divides.divmod_nat m n) = m div n"
   918   by (simp add: div_nat_def)
   942   by (simp add: div_nat_def)
   919 
   943 
   920 lemma snd_divmod_nat [simp]:
   944 lemma snd_divmod_nat [simp]:
   921   "snd (divmod_nat m n) = m mod n"
   945   "snd (Divides.divmod_nat m n) = m mod n"
   922   by (simp add: mod_nat_def)
   946   by (simp add: mod_nat_def)
   923 
   947 
   924 lemma divmod_nat_div_mod:
   948 lemma divmod_nat_div_mod:
   925   "divmod_nat m n = (m div n, m mod n)"
   949   "Divides.divmod_nat m n = (m div n, m mod n)"
   926   by (simp add: prod_eq_iff)
   950   by (simp add: prod_eq_iff)
   927 
   951 
   928 lemma div_nat_unique:
   952 lemma div_nat_unique:
   929   assumes "divmod_nat_rel m n (q, r)"
   953   assumes "divmod_nat_rel m n (q, r)"
   930   shows "m div n = q"
   954   shows "m div n = q"
   931   using assms by (auto dest!: divmod_nat_unique simp add: prod_eq_iff)
   955   using assms by (auto dest!: Divides.divmod_nat_unique simp add: prod_eq_iff)
   932 
   956 
   933 lemma mod_nat_unique:
   957 lemma mod_nat_unique:
   934   assumes "divmod_nat_rel m n (q, r)"
   958   assumes "divmod_nat_rel m n (q, r)"
   935   shows "m mod n = r"
   959   shows "m mod n = r"
   936   using assms by (auto dest!: divmod_nat_unique simp add: prod_eq_iff)
   960   using assms by (auto dest!: Divides.divmod_nat_unique simp add: prod_eq_iff)
   937 
   961 
   938 lemma divmod_nat_rel: "divmod_nat_rel m n (m div n, m mod n)"
   962 lemma divmod_nat_rel: "divmod_nat_rel m n (m div n, m mod n)"
   939   using divmod_nat_rel_divmod_nat by (simp add: divmod_nat_div_mod)
   963   using Divides.divmod_nat_rel_divmod_nat by (simp add: divmod_nat_div_mod)
   940 
       
   941 lemma divmod_nat_zero: "divmod_nat m 0 = (0, m)"
       
   942   by (simp add: divmod_nat_unique divmod_nat_rel_def)
       
   943 
       
   944 lemma divmod_nat_zero_left: "divmod_nat 0 n = (0, 0)"
       
   945   by (simp add: divmod_nat_unique divmod_nat_rel_def)
       
   946 
       
   947 lemma divmod_nat_base: "m < n \<Longrightarrow> divmod_nat m n = (0, m)"
       
   948   by (simp add: divmod_nat_unique divmod_nat_rel_def)
       
   949 
       
   950 lemma divmod_nat_step:
       
   951   assumes "0 < n" and "n \<le> m"
       
   952   shows "divmod_nat m n = (Suc ((m - n) div n), (m - n) mod n)"
       
   953 proof (rule divmod_nat_unique)
       
   954   have "divmod_nat_rel (m - n) n ((m - n) div n, (m - n) mod n)"
       
   955     by (rule divmod_nat_rel)
       
   956   thus "divmod_nat_rel m n (Suc ((m - n) div n), (m - n) mod n)"
       
   957     unfolding divmod_nat_rel_def using assms by auto
       
   958 qed
       
   959 
   964 
   960 text \<open>The ''recursion'' equations for @{const divide} and @{const mod}\<close>
   965 text \<open>The ''recursion'' equations for @{const divide} and @{const mod}\<close>
   961 
   966 
   962 lemma div_less [simp]:
   967 lemma div_less [simp]:
   963   fixes m n :: nat
   968   fixes m n :: nat
   964   assumes "m < n"
   969   assumes "m < n"
   965   shows "m div n = 0"
   970   shows "m div n = 0"
   966   using assms divmod_nat_base by (simp add: prod_eq_iff)
   971   using assms Divides.divmod_nat_base by (simp add: prod_eq_iff)
   967 
   972 
   968 lemma le_div_geq:
   973 lemma le_div_geq:
   969   fixes m n :: nat
   974   fixes m n :: nat
   970   assumes "0 < n" and "n \<le> m"
   975   assumes "0 < n" and "n \<le> m"
   971   shows "m div n = Suc ((m - n) div n)"
   976   shows "m div n = Suc ((m - n) div n)"
   972   using assms divmod_nat_step by (simp add: prod_eq_iff)
   977   using assms Divides.divmod_nat_step by (simp add: prod_eq_iff)
   973 
   978 
   974 lemma mod_less [simp]:
   979 lemma mod_less [simp]:
   975   fixes m n :: nat
   980   fixes m n :: nat
   976   assumes "m < n"
   981   assumes "m < n"
   977   shows "m mod n = m"
   982   shows "m mod n = m"
   978   using assms divmod_nat_base by (simp add: prod_eq_iff)
   983   using assms Divides.divmod_nat_base by (simp add: prod_eq_iff)
   979 
   984 
   980 lemma le_mod_geq:
   985 lemma le_mod_geq:
   981   fixes m n :: nat
   986   fixes m n :: nat
   982   assumes "n \<le> m"
   987   assumes "n \<le> m"
   983   shows "m mod n = (m - n) mod n"
   988   shows "m mod n = (m - n) mod n"
   984   using assms divmod_nat_step by (cases "n = 0") (simp_all add: prod_eq_iff)
   989   using assms Divides.divmod_nat_step by (cases "n = 0") (simp_all add: prod_eq_iff)
   985 
   990 
   986 instance proof
   991 instance proof
   987   fix m n :: nat
   992   fix m n :: nat
   988   show "m div n * n + m mod n = m"
   993   show "m div n * n + m mod n = m"
   989     using divmod_nat_rel [of m n] by (simp add: divmod_nat_rel_def)
   994     using divmod_nat_rel [of m n] by (simp add: divmod_nat_rel_def)
  1001   moreover from divmod_nat_rel have "divmod_nat_rel n q (n div q, n mod q)" .
  1006   moreover from divmod_nat_rel have "divmod_nat_rel n q (n div q, n mod q)" .
  1002   ultimately have "divmod_nat_rel (m * n) (m * q) (n div q, m * (n mod q))" .
  1007   ultimately have "divmod_nat_rel (m * n) (m * q) (n div q, m * (n mod q))" .
  1003   thus "(m * n) div (m * q) = n div q" by (rule div_nat_unique)
  1008   thus "(m * n) div (m * q) = n div q" by (rule div_nat_unique)
  1004 next
  1009 next
  1005   fix n :: nat show "n div 0 = 0"
  1010   fix n :: nat show "n div 0 = 0"
  1006     by (simp add: div_nat_def divmod_nat_zero)
  1011     by (simp add: div_nat_def Divides.divmod_nat_zero)
  1007 next
  1012 next
  1008   fix n :: nat show "0 div n = 0"
  1013   fix n :: nat show "0 div n = 0"
  1009     by (simp add: div_nat_def divmod_nat_zero_left)
  1014     by (simp add: div_nat_def Divides.divmod_nat_zero_left)
  1010 qed
  1015 qed
  1011 
  1016 
  1012 end
  1017 end
  1013 
  1018 
  1014 instantiation nat :: normalization_semidom
  1019 instantiation nat :: normalization_semidom
  1028 instance
  1033 instance
  1029   by standard (simp_all add: unit_factor_nat_def)
  1034   by standard (simp_all add: unit_factor_nat_def)
  1030   
  1035   
  1031 end
  1036 end
  1032 
  1037 
  1033 lemma divmod_nat_if [code]: "divmod_nat m n = (if n = 0 \<or> m < n then (0, m) else
  1038 lemma divmod_nat_if [code]:
  1034   let (q, r) = divmod_nat (m - n) n in (Suc q, r))"
  1039   "Divides.divmod_nat m n = (if n = 0 \<or> m < n then (0, m) else
       
  1040     let (q, r) = Divides.divmod_nat (m - n) n in (Suc q, r))"
  1035   by (simp add: prod_eq_iff case_prod_beta not_less le_div_geq le_mod_geq)
  1041   by (simp add: prod_eq_iff case_prod_beta not_less le_div_geq le_mod_geq)
  1036 
  1042 
  1037 text \<open>Simproc for cancelling @{const divide} and @{const mod}\<close>
  1043 text \<open>Simproc for cancelling @{const divide} and @{const mod}\<close>
  1038 
  1044 
  1039 ML_file "~~/src/Provers/Arith/cancel_div_mod.ML"
  1045 ML_file "~~/src/Provers/Arith/cancel_div_mod.ML"
  1345   from A B show ?lhs ..
  1351   from A B show ?lhs ..
  1346 next
  1352 next
  1347   assume P: ?lhs
  1353   assume P: ?lhs
  1348   then have "divmod_nat_rel m n (q, m - n * q)"
  1354   then have "divmod_nat_rel m n (q, m - n * q)"
  1349     unfolding divmod_nat_rel_def by (auto simp add: ac_simps)
  1355     unfolding divmod_nat_rel_def by (auto simp add: ac_simps)
  1350   with divmod_nat_rel_unique divmod_nat_rel [of m n]
  1356   then have "m div n = q"
  1351   have "(q, m - n * q) = (m div n, m mod n)" by auto
  1357     by (rule div_nat_unique)
  1352   then show ?rhs by simp
  1358   then show ?rhs by simp
  1353 qed
  1359 qed
  1354 
  1360 
  1355 theorem split_div':
  1361 theorem split_div':
  1356   "P ((m::nat) div n) = ((n = 0 \<and> P 0) \<or>
  1362   "P ((m::nat) div n) = ((n = 0 \<and> P 0) \<or>
  1357    (\<exists>q. (n * q \<le> m \<and> m < n * (Suc q)) \<and> P q))"
  1363    (\<exists>q. (n * q \<le> m \<and> m < n * (Suc q)) \<and> P q))"
  1358   apply (case_tac "0 < n")
  1364   apply (cases "0 < n")
  1359   apply (simp only: add: split_div_lemma)
  1365   apply (simp only: add: split_div_lemma)
  1360   apply simp_all
  1366   apply simp_all
  1361   done
  1367   done
  1362 
  1368 
  1363 lemma split_mod:
  1369 lemma split_mod: