(* Title: HOL/Nat.thy Author: Tobias Nipkow Author: Lawrence C Paulson Author: Markus Wenzel *)
section‹Natural numbers›
theory Nat importsInductiveTypedefFun Rings begin
subsection‹Type ‹ind›\›
typedecl ind
axiomatization Zero_Rep :: ind and Suc_Rep :: "ind ==> ind" 🍋‹The axiom of infinity in 2 parts:› where Suc_Rep_inject: "Suc_Rep x = Suc_Rep y ==> x = y" and Suc_Rep_not_Zero_Rep: "Suc_Rep x ≠ Zero_Rep"
subsection‹Type nat›
text‹Type definition›
inductive Nat :: "ind ==> bool" where
Zero_RepI: "Nat Zero_Rep"
| Suc_RepI: "Nat i ==> Nat (Suc_Rep i)"
typedef nat = "{n. Nat n}" morphisms Rep_Nat Abs_Nat using Nat.Zero_RepI by auto
lemma Nat_Rep_Nat: "Nat (Rep_Nat n)" using Rep_Nat by simp
lemma Nat_Abs_Nat_inverse: "Nat n ==> Rep_Nat (Abs_Nat n) = n" using Abs_Nat_inverse by simp
lemma Nat_Abs_Nat_inject: "Nat n ==> Nat m ==> Abs_Nat n = Abs_Nat m ⟷ n = m" using Abs_Nat_inject by simp
lemma Suc_Rep_inject': "Suc_Rep x = Suc_Rep y ⟷ x = y" by (rule iffI, rule Suc_Rep_inject) simp_all
lemma nat_induct0: assumes"P 0"and"∧n. P n ==> P (Suc n)" shows"P n" proof - have"P (Abs_Nat (Rep_Nat n))" using assms unfolding Zero_nat_def Suc_def by (iprover intro: Nat_Rep_Nat [THEN Nat.induct] elim: Nat_Abs_Nat_inverse [THEN subst]) thenshow ?thesis by (simp add: Rep_Nat_inverse) qed
free_constructors case_nat for"0 :: nat" | Suc pred where"pred (0 :: nat) = (0 :: nat)" proof atomize_elim fix n show"n = 0 ∨ (∃m. n = Suc m)" by (induction n rule: nat_induct0) auto next fix n m show"(Suc n = Suc m) = (n = m)" by (simp add: Suc_def Nat_Abs_Nat_inject Nat_Rep_Nat Suc_RepI Suc_Rep_inject' Rep_Nat_inject) next fix n show"0 ≠ Suc n" by (simp add: Suc_not_Zero) qed
🍋‹Avoid name clashes by prefixing the output of ‹old_rep_datatype›with ‹old›.› setup‹Sign.mandatory_path "old"›
old_rep_datatype "0 :: nat" Suc by (erule nat_induct0) auto
setup‹Sign.parent_path›
🍋‹But erase the prefix for properties that are not generated by ‹free_constructors›.› setup‹Sign.mandatory_path "nat"›
declare old.nat.inject[iff del] and old.nat.distinct(1)[simp del, induct_simp del]
lemma nat_induct [case_names 0 Suc, induct type: nat]: fixes n assumes"P 0"and"∧n. P n ==> P (Suc n)" shows"P n" 🍋‹for backward compatibility -- names of variables differ› using assms by (rule nat.induct)
hide_fact
nat_exhaust
nat_induct0
ML ‹ val nat_basic_lfp_sugar = let val ctr_sugar = the (Ctr_Sugar.ctr_sugar_of_global 🍋🍋‹nat›); val recx = Logic.varify_types_global 🍋‹rec_nat›; val C = body_type (fastype_of recx); in {T = HOLogic.natT, fp_res_index = 0, C = C, fun_arg_Tsss = [[], [[HOLogic.natT, C]]], ctr_sugar = ctr_sugar, recx = recx, rec_thms = @{thms nat.rec}} end; ›
setup‹ let fun basic_lfp_sugars_of _ [🍋‹nat›] _ _ ctxt = ([], [0], [nat_basic_lfp_sugar], [], [], [], TrueI (*dummy*)
| basic_lfp_sugars_of bs arg_Ts callers callssss ctxt =
BNF_LFP_Rec_Sugar.default_basic_lfp_sugars_of bs arg_Ts callers callssss ctxt; in
BNF_LFP_Rec_Sugar.register_lfp_rec_extension
{nested_simps = [], special_endgame_tac = K (K (K (K no_tac))), is_new_datatype = K (K true),
basic_lfp_sugars_of = basic_lfp_sugars_of, rewrite_nested_rec_call = NONE} end ›
text‹Injectiveness and distinctness lemmas›
lemma inj_Suc [simp]: "inj_on Suc N" by (simp add: inj_on_def)
lemma bij_betw_Suc [simp]: "bij_betw Suc M N ⟷ Suc ` M = N" by (simp add: bij_betw_def)
lemma Suc_neq_Zero: "Suc m = 0 ==> R" by (rule notE) (rule Suc_not_Zero)
lemma Zero_neq_Suc: "0 = Suc m ==> R" by (rule Suc_neq_Zero) (erule sym)
lemma Suc_inject: "Suc x = Suc y ==> x = y" by (rule inj_Suc [THEN injD])
lemma n_not_Suc_n: "n ≠ Suc n" by (induct n) simp_all
lemma Suc_n_not_n: "Suc n ≠ n" by (rule not_sym) (rule n_not_Suc_n)
text‹A special form of induction for reasoning about 🍋‹m 🚫› and 🍋‹m - n›.› lemma diff_induct: assumes"∧x. P x 0" and"∧y. P 0 (Suc y)" and"∧x y. P x y ==> P (Suc x) (Suc y)" shows"P m n" proof (induct n arbitrary: m) case 0 show ?caseby (rule assms(1)) next case (Suc n) show ?case proof (induct m) case 0 show ?caseby (rule assms(2)) next case (Suc m) from‹P m n›show ?caseby (rule assms(3)) qed qed
subsection‹Arithmetic operators›
instantiation nat :: comm_monoid_diff begin
primrec plus_nat where
add_0 [code]: "0 + n = (n::nat)"
| add_Suc: "Suc m + n = Suc (m + n)"
lemma add_0_right [simp]: "m + 0 = m" for m :: nat by (induct m) simp_all
lemma add_Suc_right [simp]: "m + Suc n = Suc (m + n)" by (induct m) simp_all
lemma add_Suc_shift [code]: "Suc m + n = m + Suc n" by simp
primrec minus_nat where
diff_0 [code]: "m - 0 = (m::nat)"
| diff_Suc: "m - Suc n = (case m - n of 0 ==> 0 | Suc k ==> k)"
declare diff_Suc [simp del]
lemma diff_0_eq_0 [simp, code]: "0 - n = 0" for n :: nat by (induct n) (simp_all add: diff_Suc)
lemma diff_Suc_Suc [simp, code]: "Suc m - Suc n = m - n" by (induct n) (simp_all add: diff_Suc)
instance proof fix n m q :: nat show"(n + m) + q = n + (m + q)"by (induct n) simp_all show"n + m = m + n"by (induct n) simp_all show"m + n - m = n"by (induct m) simp_all show"n - m - q = n - (m + q)"by (induct q) (simp_all add: diff_Suc) show"0 + n = n"by simp show"0 - n = 0"by simp qed
end
hide_fact (open) add_0 add_0_right diff_0
instantiation nat :: comm_semiring_1_cancel begin
definition One_nat_def [simp]: "1 = Suc 0"
primrec times_nat where
mult_0: "0 * n = (0::nat)"
| mult_Suc: "Suc m * n = n + (m * n)"
lemma mult_0_right [simp]: "m * 0 = 0" for m :: nat by (induct m) simp_all
lemma mult_Suc_right [simp]: "m * Suc n = m + (m * n)" by (induct m) (simp_all add: add.left_commute)
lemma add_mult_distrib: "(m + n) * k = (m * k) + (n * k)" for m n k :: nat by (induct m) (simp_all add: add.assoc)
instance proof fix k n m q :: nat show"0 ≠ (1::nat)" by simp show"1 * n = n" by simp show"n * m = m * n" by (induct n) simp_all show"(n * m) * q = n * (m * q)" by (induct n) (simp_all add: add_mult_distrib) show"(n + m) * q = n * q + m * q" by (rule add_mult_distrib) show"k * (m - n) = (k * m) - (k * n)" by (induct m n rule: diff_induct) simp_all qed
end
subsubsection ‹Addition›
text‹Reasoning about ‹m + 0 = 0›, etc.›
lemma add_is_0 [iff]: "m + n = 0 ⟷ m = 0 ∧ n = 0" for m n :: nat by (cases m) simp_all
lemma add_is_1: "m + n = Suc 0 ⟷ m = Suc 0 ∧ n = 0 ∨ m = 0 ∧ n = Suc 0" by (cases m) simp_all
lemma one_is_add: "Suc 0 = m + n ⟷ m = Suc 0 ∧ n = 0 ∨ m = 0 ∧ n = Suc 0" by (rule trans, rule eq_commute, rule add_is_1)
lemma add_eq_self_zero: "m + n = m ==> n = 0" for m n :: nat by (induct m) simp_all
lemma plus_1_eq_Suc: "plus 1 = Suc" by (simp add: fun_eq_iff)
lemma Suc_eq_plus1: "Suc n = n + 1" by simp
lemma Suc_eq_plus1_left: "Suc n = 1 + n" by simp
subsubsection ‹Difference›
lemma Suc_diff_diff [simp]: "(Suc m - n) - Suc k = m - n - k" by (simp add: diff_diff_add)
lemma diff_Suc_1: "Suc n - 1 = n" by simp
lemma diff_Suc_1' [simp]: "Suc n - Suc 0 = n" by simp
subsubsection ‹Multiplication›
lemma mult_is_0 [simp]: "m * n = 0 ⟷ m = 0 ∨ n = 0"for m n :: nat by (induct m) auto
lemma mult_eq_1_iff [simp]: "m * n = Suc 0 ⟷ m = Suc 0 ∧ n = Suc 0" proof (induct m) case 0 thenshow ?caseby simp next case (Suc m) thenshow ?caseby (induct n) auto qed
lemma one_eq_mult_iff [simp]: "Suc 0 = m * n ⟷ m = Suc 0 ∧ n = Suc 0" by (simp add: eq_commute flip: mult_eq_1_iff)
lemma nat_mult_eq_1_iff [simp]: "m * n = 1 ⟷ m = 1 ∧ n = 1" and nat_1_eq_mult_iff [simp]: "1 = m * n ⟷ m = 1 ∧ n = 1"for m n :: nat by auto
lemma mult_cancel1 [simp]: "k * m = k * n ⟷ m = n ∨ k = 0" for k m n :: nat proof - have"k ≠ 0 ==> k * m = k * n ==> m = n" proof (induct n arbitrary: m) case 0 thenshow"m = 0"by simp next case (Suc n) thenshow"m = Suc n" by (cases m) (simp_all add: eq_commute [of 0]) qed thenshow ?thesis by auto qed
lemma mult_cancel2 [simp]: "m * k = n * k ⟷ m = n ∨ k = 0" for k m n :: nat by (simp add: mult.commute)
lemma Suc_mult_cancel1: "Suc k * m = Suc k * n ⟷ m = n" by (subst mult_cancel1) simp
subsection‹Orders on 🍋‹nat›\
subsubsection ‹Operation definition›
instantiation nat :: linorder begin
primrec less_eq_nat where "(0::nat) ≤ n ⟷ True"
| "Suc m ≤ n ⟷ (case n of 0 ==> False | Suc n ==> m ≤ n)"
declare less_eq_nat.simps [simp del]
lemma le0 [iff]: "0 ≤ n"for
n :: nat by (simp add: less_eq_nat.simps)
lemma [code]: "0 ≤ n ⟷ True" for n :: nat by simp
definition less_nat where less_eq_Suc_le: "n < m ⟷ Suc n ≤ m"
lemma Suc_le_mono [iff]: "Suc n ≤ Suc m ⟷ n ≤ m" by (simp add: less_eq_nat.simps(2))
lemma Suc_le_eq [code]: "Suc m ≤ n ⟷ m < n" unfolding less_eq_Suc_le ..
lemma le_0_eq [iff]: "n ≤ 0 ⟷ n = 0" for n :: nat by (induct n) (simp_all add: less_eq_nat.simps(2))
lemma not_less0 [iff]: "¬ n < 0" for n :: nat by (simp add: less_eq_Suc_le)
lemma less_nat_zero_code [code]: "n < 0 ⟷ False" for n :: nat by simp
lemma Suc_less_eq [iff]: "Suc m < Suc n ⟷ m < n" by (simp add: less_eq_Suc_le)
lemma less_Suc_eq_le [code]: "m < Suc n ⟷ m ≤ n" by (simp add: less_eq_Suc_le)
lemma Suc_less_eq2: "Suc n < m ⟷ (∃m'. m = Suc m' ∧ n < m')" by (cases m) auto
lemma le_SucI: "m ≤ n ==> m ≤ Suc n" by (induct m arbitrary: n) (simp_all add: less_eq_nat.simps(2) split: nat.splits)
lemma Suc_leD: "Suc m ≤ n ==> m ≤ n" by (cases n) (auto intro: le_SucI)
lemma less_SucI: "m < n ==> m < Suc n" by (simp add: less_eq_Suc_le) (erule Suc_leD)
lemma Suc_lessD: "Suc m < n ==> m < n" by (simp add: less_eq_Suc_le) (erule Suc_leD)
instance proof fix n m q :: nat show"n < m ⟷ n ≤ m ∧¬ m ≤ n" proof (induct n arbitrary: m) case 0 thenshow ?case by (cases m) (simp_all add: less_eq_Suc_le) next case (Suc n) thenshow ?case by (cases m) (simp_all add: less_eq_Suc_le) qed show"n ≤ n" by (induct n) simp_all thenshow"n = m"if"n ≤ m"and"m ≤ n" using that by (induct n arbitrary: m)
(simp_all add: less_eq_nat.simps(2) split: nat.splits) show"n ≤ q"if"n ≤ m"and"m ≤ q" using that proof (induct n arbitrary: m q) case 0 show ?caseby simp next case (Suc n) thenshow ?case by (simp_all (no_asm_use) add: less_eq_nat.simps(2) split: nat.splits, clarify,
simp_all (no_asm_use) add: less_eq_nat.simps(2) split: nat.splits, clarify,
simp_all (no_asm_use) add: less_eq_nat.simps(2) split: nat.splits) qed show"n ≤ m ∨ m ≤ n" by (induct n arbitrary: m)
(simp_all add: less_eq_nat.simps(2) split: nat.splits) qed
end
instantiation nat :: order_bot begin
definition bot_nat :: nat where"bot_nat = 0"
instance by standard (simp add: bot_nat_def)
end
instance nat :: no_top by standard (auto intro: less_Suc_eq_le [THEN iffD2])
lemma less_one [iff]: "n < 1 ⟷ n = 0" for n :: nat unfolding One_nat_def by (rule less_Suc0)
lemma Suc_mono: "m < n ==> Suc m < Suc n" by simp
text‹"Less than" is antisymmetric, sort of.› lemma less_antisym: "¬ n < m ==> n < Suc m ==> m = n" unfolding not_less less_Suc_eq_le by (rule antisym)
lemma nat_neq_iff: "m ≠ n ⟷ m < n ∨ n < m" for m n :: nat by (rule linorder_neq_iff)
subsubsection ‹Inductive (?) properties›
lemma Suc_lessI: "m < n ==> Suc m ≠ n ==> Suc m < n" unfolding less_eq_Suc_le [of m] le_less by simp
lemma lessE: assumes major: "i < k" and 1: "k = Suc i ==> P" and 2: "∧j. i < j ==> k = Suc j ==> P" shows P proof - from major have"∃j. i ≤ j ∧ k = Suc j" unfolding less_eq_Suc_le by (induct k) simp_all thenhave"(∃j. i < j ∧ k = Suc j) ∨ k = Suc i" by (auto simp add: less_le) with 1 2 show P by auto qed
lemma less_SucE: assumes major: "m < Suc n" and less: "m < n ==> P" and eq: "m = n ==> P" shows P proof (rule major [THEN lessE]) show"Suc n = Suc m ==> P" using eq by blast show"∧j. [m < j; Suc n = Suc j]==> P" by (blast intro: less) qed
lemma Suc_lessE: assumes major: "Suc i < k" and minor: "∧j. i < j ==> k = Suc j ==> P" shows P proof (rule major [THEN lessE]) show"k = Suc (Suc i) ==> P" using lessI minor by iprover show"∧j. [Suc i < j; k = Suc j]==> P" using Suc_lessD minor by iprover qed
lemma Suc_less_SucD: "Suc m < Suc n ==> m < n" by simp
lemma less_trans_Suc: assumes le: "i < j" shows"j < k ==> Suc i < k" proof (induct k) case 0 thenshow ?caseby simp next case (Suc k) with le show ?case by simp (auto simp add: less_Suc_eq dest: Suc_lessD) qed
text‹Can be used with ‹less_Suc_eq›to get 🍋‹n = m ∨ n 🚫›.› lemma not_less_eq: "¬ m < n ⟷ n < Suc m" by (simp only: not_less less_Suc_eq_le)
lemma not_less_eq_eq: "¬ m ≤ n ⟷ Suc n ≤ m" by (simp only: not_le Suc_le_eq)
text‹Properties of "less than or equal".›
lemma le_imp_less_Suc: "m ≤ n ==> m < Suc n" by (simp only: less_Suc_eq_le)
lemma Suc_n_not_le_n: "¬ Suc n ≤ n" by (simp add: not_le less_Suc_eq_le)
lemma le_Suc_eq: "m ≤ Suc n ⟷ m ≤ n ∨ m = Suc n" by (simp add: less_Suc_eq_le [symmetric] less_Suc_eq)
lemma le_SucE: "m ≤ Suc n ==> (m ≤ n ==> R) ==> (m = Suc n ==> R) ==> R" by (drule le_Suc_eq [THEN iffD1], iprover+)
lemma Suc_leI: "m < n ==> Suc m ≤ n" by (simp only: Suc_le_eq)
text‹Stronger version of ‹Suc_leD›.› lemma Suc_le_lessD: "Suc m ≤ n ==> m < n" by (simp only: Suc_le_eq)
lemma less_imp_le_nat: "m < n ==> m ≤ n"for m n :: nat unfolding less_eq_Suc_le by (rule Suc_leD)
text‹For instance, ‹(Suc m 🚫 n) = (Suc m ≤ n) = (m 🚫)›\› lemmas le_simps = less_imp_le_nat less_Suc_eq_le Suc_le_eq
text‹Equivalence of ‹m ≤ n›and ‹m 🚫∨ m = n›\›
lemma less_or_eq_imp_le: "m < n ∨ m = n ==> m ≤ n" for m n :: nat unfolding le_less .
lemma le_eq_less_or_eq: "m ≤ n ⟷ m < n ∨ m = n" for m n :: nat by (rule le_less)
text‹Useful with ‹blast›.› lemma eq_imp_le: "m = n ==> m ≤ n" for m n :: nat by auto
lemma le_refl: "n ≤ n" for n :: nat by simp
lemma le_trans: "i ≤ j ==> j ≤ k ==> i ≤ k" for i j k :: nat by (rule order_trans)
lemma le_antisym: "m ≤ n ==> n ≤ m ==> m = n" for m n :: nat by (rule antisym)
lemma nat_less_le: "m < n ⟷ m ≤ n ∧ m ≠ n" for m n :: nat by (rule less_le)
lemma le_neq_implies_less: "m ≤ n ==> m ≠ n ==> m < n" for m n :: nat unfolding less_le ..
lemma nat_le_linear: "m ≤ n ∨ n ≤ m" for m n :: nat by (rule linear)
lemmas linorder_neqE_nat = linorder_neqE [where 'a = nat]
lemma le_less_Suc_eq: "m ≤ n ==> n < Suc m ⟷ n = m" unfolding less_Suc_eq_le by auto
lemma not_less_less_Suc_eq: "¬ n < m ==> n < Suc m ⟷ n = m" unfolding not_less by (rule le_less_Suc_eq)
lemma not0_implies_Suc: "n ≠ 0 ==>∃m. n = Suc m" by (cases n) simp_all
lemma gr0_implies_Suc: "n > 0 ==>∃m. n = Suc m" by (cases n) simp_all
lemma gr_implies_not0: "m < n ==> n ≠ 0" for m n :: nat by (cases n) simp_all
lemma neq0_conv[iff]: "n ≠ 0 ⟷ 0 < n" for n :: nat by (cases n) simp_all
text‹This theorem is useful with ‹blast›\› lemma gr0I: "(n = 0 ==> False) ==> 0 < n" for n :: nat by (rule neq0_conv[THEN iffD1]) iprover
lemma gr0_conv_Suc: "0 < n ⟷ (∃m. n = Suc m)" by (fast intro: not0_implies_Suc)
lemma not_gr0 [iff]: "¬ 0 < n ⟷ n = 0" for n :: nat using neq0_conv by blast
lemma Suc_le_D: "Suc n ≤ m' ==>∃m. m' = Suc m" by (induct m') simp_all
text‹Useful in certain inductive arguments› lemma less_Suc_eq_0_disj: "m < Suc n ⟷ m = 0 ∨ (∃j. m = Suc j ∧ j < n)" by (cases m) simp_all
lemma All_less_Suc: "(∀i < Suc n. P i) = (P n ∧ (∀i < n. P i))" by (auto simp: less_Suc_eq)
lemma All_less_Suc2: "(∀i < Suc n. P i) = (P 0 ∧ (∀i < n. P(Suc i)))" by (auto simp: less_Suc_eq_0_disj)
lemma Ex_less_Suc: "(∃i < Suc n. P i) = (P n ∨ (∃i < n. P i))" by (auto simp: less_Suc_eq)
lemma Ex_less_Suc2: "(∃i < Suc n. P i) = (P 0 ∨ (∃i < n. P(Suc i)))" by (auto simp: less_Suc_eq_0_disj)
text‹@{term mono} (non-strict) doesn't imply increasing, as the function could be constant› lemma strict_mono_imp_increasing: fixes n::nat assumes"strict_mono f"shows"f n ≥ n" proof (induction n) case 0 thenshow ?case by auto next case (Suc n) thenshow ?case unfolding not_less_eq_eq [symmetric] using Suc_n_not_le_n assms order_trans strict_mono_less_eq by blast qed
lemma Suc_diff_1 [simp]: "0 < n ==> Suc (n - 1) = n" unfolding One_nat_def by (rule Suc_pred)
lemma nat_add_left_cancel_le [simp]: "k + m ≤ k + n ⟷ m ≤ n" for k m n :: nat by (induct k) simp_all
lemma nat_add_left_cancel_less [simp]: "k + m < k + n ⟷ m < n" for k m n :: nat by (induct k) simp_all
lemma add_gr_0 [iff]: "m + n > 0 ⟷ m > 0 ∨ n > 0" for m n :: nat by (auto dest: gr0_implies_Suc)
text‹strict, in 1st argument› lemma add_less_mono1: "i < j ==> i + k < j + k" for i j k :: nat by (induct k) simp_all
text‹strict, in both arguments› lemma add_less_mono: fixes i j k l :: nat assumes"i < j""k < l"shows"i + k < j + l" proof - have"i + k < j + k" by (simp add: add_less_mono1 assms) alsohave"... < j + l" using‹i 🚫›by (induction j) (auto simp: assms) finallyshow ?thesis . qed
lemma less_imp_Suc_add: "m < n ==>∃k. n = Suc (m + k)" proof (induct n) case 0 thenshow ?caseby simp next case Suc thenshow ?case by (simp add: order_le_less)
(blast elim!: less_SucE intro!: Nat.add_0_right [symmetric] add_Suc_right [symmetric]) qed
lemma le_Suc_ex: "k ≤ l ==> (∃n. l = k + n)" for k l :: nat by (auto simp: less_Suc_eq_le[symmetric] dest: less_imp_Suc_add)
lemma less_natE: assumes‹m 🚫› obtains q where‹n = Suc (m + q)› using assms by (auto dest: less_imp_Suc_add intro: that)
text‹strict, in 1st argument; proof is by induction on ‹k > 0›\› lemma mult_less_mono2: fixes i j :: nat assumes"i < j"and"0 < k" shows"k * i < k * j" using‹0 🚫› proof (induct k) case 0 thenshow ?caseby simp next case (Suc k) with‹i 🚫›show ?case by (cases k) (simp_all add: add_less_mono) qed
text‹Addition is the inverse of subtraction: if 🍋‹n ≤ m›then 🍋‹n + (m - n) = m›.› lemma add_diff_inverse_nat: "¬ m < n ==> n + (m - n) = m" for m n :: nat by (induct m n rule: diff_induct) simp_all
lemma nat_le_iff_add: "m ≤ n ⟷ (∃k. n = m + k)" for m n :: nat using nat_add_left_cancel_le[of m 0] by (auto dest: le_Suc_ex)
text‹The naturals form an ordered ‹semidom›and a ‹dioid›.›
instance nat :: discrete_linordered_semidom proof fix m n q :: nat show‹0 🚫1::nat)› by simp show‹m ≤ n ==> q + m ≤ q + n› by simp show‹m 🚫==> 0 🚫==> q * m 🚫 * n› by (simp add: mult_less_mono2) show‹m ≠ 0 ==> n ≠ 0 ==> m * n ≠ 0› by simp show‹n ≤ m ==> (m - n) + n = m› by (simp add: add_diff_inverse_nat add.commute linorder_not_less) show‹m 🚫⟷ m + 1 ≤ n› by (simp add: Suc_le_eq) qed
instance nat :: dioid by standard (rule nat_le_iff_add)
declare le0[simp del] 🍋‹This is now @{thm zero_le}› declare le_0_eq[simp del] 🍋‹This is now @{thm le_zero_eq}› declare not_less0[simp del] 🍋‹This is now @{thm not_less_zero}› declare not_gr0[simp del] 🍋‹This is now @{thm not_gr_zero}›
global_interpretation bot_nat_0: ordering_top ‹(≥)›‹(>)›‹0::nat› by standard simp
global_interpretation max_nat: semilattice_neutr_order max ‹0::nat›‹(≥)›‹(>)› by standard (simp add: max_def)
lemma mono_Suc: "mono Suc" by (rule monoI) simp
lemma min_0L [simp]: "min 0 n = 0" for n :: nat by (rule min_absorb1) simp
lemma min_0R [simp]: "min n 0 = 0" for n :: nat by (rule min_absorb2) simp
lemma min_Suc_Suc [simp]: "min (Suc m) (Suc n) = Suc (min m n)" by (simp add: mono_Suc min_of_mono)
lemma min_Suc1: "min (Suc n) m = (case m of 0 ==> 0 | Suc m' ==> Suc(min n m'))" by (simp split: nat.split)
lemma min_Suc2: "min m (Suc n) = (case m of 0 ==> 0 | Suc m' ==> Suc(min m' n))" by (simp split: nat.split)
lemma max_0L [simp]: "max 0 n = n" for n :: nat by (fact max_nat.left_neutral)
lemma max_0R [simp]: "max n 0 = n" for n :: nat by (fact max_nat.right_neutral)
lemma max_Suc_Suc [simp]: "max (Suc m) (Suc n) = Suc (max m n)" by (simp add: mono_Suc max_of_mono)
lemma max_Suc1: "max (Suc n) m = (case m of 0 ==> Suc n | Suc m' ==> Suc (max n m'))" by (simp split: nat.split)
lemma max_Suc2: "max m (Suc n) = (case m of 0 ==> Suc n | Suc m' ==> Suc (max m' n))" by (simp split: nat.split)
lemma nat_mult_min_left: "min m n * q = min (m * q) (n * q)" for m n q :: nat by (simp add: min_def not_le)
(auto dest: mult_right_le_imp_le mult_right_less_imp_less le_less_trans)
lemma nat_mult_min_right: "m * min n q = min (m * n) (m * q)" for m n q :: nat by (simp add: min_def not_le)
(auto dest: mult_left_le_imp_le mult_left_less_imp_less le_less_trans)
lemma nat_add_max_left: "max m n + q = max (m + q) (n + q)" for m n q :: nat by (simp add: max_def)
lemma nat_add_max_right: "m + max n q = max (m + n) (m + q)" for m n q :: nat by (simp add: max_def)
lemma nat_mult_max_left: "max m n * q = max (m * q) (n * q)" for m n q :: nat by (simp add: max_def not_le)
(auto dest: mult_right_le_imp_le mult_right_less_imp_less le_less_trans)
lemma nat_mult_max_right: "m * max n q = max (m * n) (m * q)" for m n q :: nat by (simp add: max_def not_le)
(auto dest: mult_left_le_imp_le mult_left_less_imp_less le_less_trans)
instance nat :: wellorder proof fix P and n :: nat assume step: "(∧m. m < n ==> P m) ==> P n"for n :: nat have"∧q. q ≤ n ==> P q" proof (induct n) case (0 n) have"P 0"by (rule step) auto with 0 show ?caseby auto next case (Suc m n) thenhave"n ≤ m ∨ n = Suc m" by (simp add: le_Suc_eq) thenshow ?case proof assume"n ≤ m" thenshow"P n"by (rule Suc(1)) next assume n: "n = Suc m" show"P n"by (rule step) (rule Suc(1), simp add: n le_simps) qed qed thenshow"P n"by auto qed
lemma Least_eq_0[simp]: "P 0 ==> Least P = 0" for P :: "nat ==> bool" by (rule Least_equality[OF _ le0])
lemma Least_Suc: assumes"P n""¬ P 0" shows"(LEAST n. P n) = Suc (LEAST m. P (Suc m))" proof (cases n) case (Suc m) show ?thesis proof (rule antisym) show"(LEAST x. P x) ≤ Suc (LEAST x. P (Suc x))" using assms Suc by (force intro: LeastI Least_le) have🍋: "P (LEAST x. P x)" by (blast intro: LeastI assms) show"Suc (LEAST m. P (Suc m)) ≤ (LEAST n. P n)" proof (cases "(LEAST n. P n)") case 0 thenshow ?thesis using🍋by (simp add: assms) next case Suc with🍋show ?thesis by (auto simp: Least_le) qed qed qed (use assms in auto)
lemma Least_Suc2: "P n ==> Q m ==>¬ P 0 ==>∀k. P (Suc k) = Q k ==> Least P = Suc (Least Q)" by (erule (1) Least_Suc [THEN ssubst]) simp
lemma ex_least_nat_le: fixes P :: "nat ==> bool" assumes"P n" shows"∃k≤n. (∀i¬ P i) ∧ P k" proof (cases n) case (Suc m) with assms show ?thesis by (blast intro: Least_le LeastI_ex dest: not_less_Least) qed (use assms in auto)
lemma ex_least_nat_less: fixes P :: "nat ==> bool" assumes"P n""¬ P 0" shows"∃k∀i≤k. ¬ P i) ∧ P (Suc k)" proof (cases n) case (Suc m) thenobtain k where k: "k ≤ n""∀i¬ P i" "P k" using ex_least_nat_le ‹P n›by blast show ?thesis by (cases k) (use assms k less_eq_Suc_le in auto) qed (use assms in auto)
lemma nat_less_induct: fixes P :: "nat ==> bool" assumes"∧n. ∀m. m < n ⟶ P m ==> P n" shows"P n" using assms less_induct by blast
lemma measure_induct_rule [case_names less]: fixes f :: "'a ==> 'b::wellorder" assumes step: "∧x. (∧y. f y < f x ==> P y) ==> P x" shows"P a" by (induct m ≡"f a" arbitrary: a rule: less_induct) (auto intro: step)
text‹old style induction rules:› lemma measure_induct: fixes f :: "'a ==> 'b::wellorder" shows"(∧x. ∀y. f y < f x ⟶ P y ==> P x) ==> P a" by (rule measure_induct_rule [of f P a]) iprover
lemma full_nat_induct: assumes step: "∧n. (∀m. Suc m ≤ n ⟶ P m) ==> P n" shows"P n" by (rule less_induct) (auto intro: step simp:le_simps)
text‹An induction rule for establishing binary relations› lemma less_Suc_induct [consumes 1]: assumes less: "i < j" and step: "∧i. P i (Suc i)" and trans: "∧i j k. i < j ==> j < k ==> P i j ==> P j k ==> P i k" shows"P i j" proof - from less obtain k where j: "j = Suc (i + k)" by (auto dest: less_imp_Suc_add) have"P i (Suc (i + k))" proof (induct k) case 0 show ?caseby (simp add: step) next case (Suc k) have"0 + i < Suc k + i"by (rule add_less_mono1) simp thenhave"i < Suc (i + k)"by (simp add: add.commute) from trans[OF this lessI Suc step] show ?caseby simp qed thenshow"P i j"by (simp add: j) qed
text‹ The method of infinite descent, frequently used in number theory. Provided by Roelof Oosterhuis. ‹P n›is true for all natural numbers if 🪙 case ``0'': given ‹n = 0›prove ‹P n› 🪙 case ``smaller'': given ‹n > 0›and ‹¬ P n› prove there exists a smaller natural number ‹m›such that ‹¬ P m›. ›
lemma infinite_descent: "(∧n. ¬ P n ==>∃m¬ P m) ==> P n" for P :: "nat ==> bool" 🍋‹compact version without explicit base case› by (induct n rule: less_induct) auto
lemma infinite_descent0 [case_names 0 smaller]: fixes P :: "nat ==> bool" assumes"P 0" and"∧n. n > 0 ==>¬ P n ==>∃m. m < n ∧¬ P m" shows"P n" proof (rule infinite_descent) fix n show"¬ P n ==>∃m¬ P m" using assms by (cases "n > 0") auto qed
text‹ Infinite descent using a mapping to ‹nat›: ‹P x›is true for all ‹x ∈ D› if there exists a ‹V ∈ D ==> nat› and 🪙 case ``0'': given ‹V x = 0›prove ‹P x› 🪙 ``smaller'': given ‹V x > 0›and ‹¬ P x› prove there exists a ‹y ∈ D›such that ‹V y 🚫 x› and ‹¬ P y›. › corollary infinite_descent0_measure [case_names 0 smaller]: fixes V :: "'a ==> nat" assumes 1: "∧x. V x = 0 ==> P x" and 2: "∧x. V x > 0 ==>¬ P x ==>∃y. V y < V x ∧¬ P y" shows"P x" proof - obtain n where"n = V x"by auto moreoverhave"∧x. V x = n ==> P x" proof (induct n rule: infinite_descent0) case 0 with 1 show"P x"by auto next case (smaller n) thenobtain x where *: "V x = n "and"V x > 0 ∧¬ P x"by auto with 2 obtain y where"V y < V x ∧¬ P y"by auto with * obtain m where"m = V y ∧ m < n ∧¬ P y"by auto thenshow ?caseby auto qed ultimatelyshow"P x"by auto qed
text‹Again, without explicit base case:› lemma infinite_descent_measure: fixes V :: "'a ==> nat" assumes"∧x. ¬ P x ==>∃y. V y < V x ∧¬ P y" shows"P x" proof - from assms obtain n where"n = V x"by auto moreoverhave"∧x. V x = n ==> P x" proof - have"∃m < V x. ∃y. V y = m ∧¬ P y"if"¬ P x"for x using assms and that by auto thenshow"∧x. V x = n ==> P x" by (induct n rule: infinite_descent, auto) qed ultimatelyshow"P x"by auto qed
text‹A (clumsy) way of lifting ‹🚫close> monotonicity to ‹≤›monotonicity› lemma less_mono_imp_le_mono: fixes f :: "nat ==> nat" and i j :: nat assumes "∧i j::nat. i 🚫==> f i 🚫 j" and "i ≤ j" shows "f i ≤ f j" using assms by (auto simp add: order_le_less) text ‹non-strict, in 1st argument› lemma add_le_mono1: "i ≤ j ==> i + k ≤ j + k" for i j k :: nat by (rule add_right_mono) text ‹non-strict, in both arguments› lemma add_le_mono: "i ≤ j ==> k ≤ l ==> i + k ≤ j + l" for i j k l :: nat by (rule add_mono) lemma le_add2: "n ≤ m + n" for m n :: nat by simp lemma le_add1: "n ≤ n + m" for m n :: nat by simp lemma less_add_Suc1: "i 🚫 (i + m)" by (rule le_less_trans, rule le_add1, rule lessI) lemma less_add_Suc2: "i 🚫 (m + i)" by (rule le_less_trans, rule le_add2, rule lessI) lemma less_iff_Suc_add: "m 🚫⟷ (∃k. n = Suc (m + k))" by (iprover intro!: less_add_Suc1 less_imp_Suc_add) lemma trans_le_add1: "i ≤ j ==> i ≤ j + m" for i j m :: nat by (rule le_trans, assumption, rule le_add1) lemma trans_le_add2: "i ≤ j ==> i ≤ m + j" for i j m :: nat by (rule le_trans, assumption, rule le_add2) lemma trans_less_add1: "i 🚫==> i 🚫 + m" for i j m :: nat by (rule less_le_trans, assumption, rule le_add1) lemma trans_less_add2: "i 🚫==> i 🚫 + j" for i j m :: nat by (rule less_le_trans, assumption, rule le_add2) lemma add_lessD1: "i + j 🚫==> i 🚫" for i j k :: nat by (rule le_less_trans [of _ "i+j"]) (simp_all add: le_add1) lemma not_add_less1 [iff]: "¬ i + j 🚫" for i j :: nat by simp lemma not_add_less2 [iff]: "¬ j + i 🚫" for i j :: nat by simp lemma add_leD1: "m + k ≤ n ==> m ≤ n" for k m n :: nat by (rule order_trans [of _ "m + k"]) (simp_all add: le_add1) lemma add_leD2: "m + k ≤ n ==> k ≤ n" for k m n :: nat by (force simp add: add.commute dest: add_leD1) lemma add_leE: "m + k ≤ n ==> (m ≤ n ==> k ≤ n ==> R) ==> R" for k m n :: nat by (blast dest: add_leD1 add_leD2) text ‹needs ‹∧k›for ‹ac_simps› to work› lemma less_add_eq_less: "∧k. k 🚫==> m + l = k + n ==> m 🚫" for l m n :: nat by (force simp del: add_Suc_right simp add: less_iff_Suc_add add_Suc_right [symmetric] ac_simps) subsubsection ‹More results about difference› lemma Suc_diff_le: "n ≤ m ==> Suc m - n = Suc (m - n)" by (induct m n rule: diff_induct) simp_all lemma diff_less_Suc: "m - n 🚫 m" by (induct m n rule: diff_induct) (auto simp: less_Suc_eq) lemma diff_le_self [simp]: "m - n ≤ m" for m n :: nat by (induct m n rule: diff_induct) (simp_all add: le_SucI) lemma less_imp_diff_less: "j 🚫==> j - n 🚫" for j k n :: nat by (rule le_less_trans, rule diff_le_self) lemma diff_Suc_less [simp]: "0 🚫==> n - Suc i 🚫" by (cases n) (auto simp add: le_simps) lemma diff_add_assoc: "k ≤ j ==> (i + j) - k = i + (j - k)" for i j k :: nat by (fact ordered_cancel_comm_monoid_diff_class.diff_add_assoc) lemma add_diff_assoc [simp]: "k ≤ j ==> i + (j - k) = i + j - k" for i j k :: nat by (fact ordered_cancel_comm_monoid_diff_class.add_diff_assoc) lemma diff_add_assoc2: "k ≤ j ==> (j + i) - k = (j - k) + i" for i j k :: nat by (fact ordered_cancel_comm_monoid_diff_class.diff_add_assoc2) lemma add_diff_assoc2 [simp]: "k ≤ j ==> j - k + i = j + i - k" for i j k :: nat by (fact ordered_cancel_comm_monoid_diff_class.add_diff_assoc2) lemma le_imp_diff_is_add: "i ≤ j ==> (j - i = k) = (j = k + i)" for i j k :: nat by auto lemma diff_is_0_eq [simp]: "m - n = 0 ⟷ m ≤ n" for m n :: nat by (induct m n rule: diff_induct) simp_all lemma diff_is_0_eq' [simp]: "m ≤ n ==> m - n = 0" for m n :: nat by simp lemma zero_less_diff [simp]: "0 🚫 - m ⟷ m 🚫" for m n :: nat by (induct m n rule: diff_induct) simp_all lemma less_imp_add_positive: assumes "i 🚫" shows "∃k::nat. 0 🚫∧ i + k = j" proof from assms show "0 🚫 - i ∧ i + (j - i) = j" by (simp add: order_less_imp_le) qed text ‹a nice rewrite for bounded subtraction› lemma nat_minus_add_max: "n - m + m = max n m" for m n :: nat by (simp add: max_def not_le order_less_imp_le) lemma nat_diff_split: "P (a - b) ⟷ (a 🚫⟶ P 0) ∧ (∀d. a = b + d ⟶ P d)" for a b :: nat 🍋‹elimination of ‹-›on ‹nat›\› by (cases "a 🚫") (auto simp add: not_less le_less dest!: add_eq_self_zero [OF sym]) lemma nat_diff_split_asm: "P (a - b) ⟷¬ (a 🚫∧¬ P 0 ∨ (∃d. a = b + d ∧¬ P d))" for a b :: nat 🍋‹elimination of ‹-›on ‹nat› in assumptions› by (auto split: nat_diff_split) lemmas nat_diff_splits = nat_diff_split nat_diff_split_asm lemma Suc_pred': "0 🚫==> n = Suc(n - 1)" by simp lemma add_eq_if: "m + n = (if m = 0 then n else Suc ((m - 1) + n))" unfolding One_nat_def by (cases m) simp_all lemma mult_eq_if: "m * n = (if m = 0 then 0 else n + ((m - 1) * n))" for m n :: nat by (cases m) simp_all lemma Suc_diff_eq_diff_pred: "0 🚫==> Suc m - n = m - (n - 1)" by (cases n) simp_all lemma diff_Suc_eq_diff_pred: "m - Suc n = (m - 1) - n" by (cases m) simp_all lemma Let_Suc [simp]: "Let (Suc n) f ≡ f (Suc n)" by (fact Let_def) subsubsection ‹Monotonicity of multiplication› lemma mult_le_mono1: "i ≤ j ==> i * k ≤ j * k" for i j k :: nat by (simp add: mult_right_mono) lemma mult_le_mono2: "i ≤ j ==> k * i ≤ k * j" for i j k :: nat by (simp add: mult_left_mono) text ‹‹≤›monotonicity, BOTH arguments› lemma mult_le_mono: "i ≤ j ==> k ≤ l ==> i * k ≤ j * l" for i j k l :: nat by (simp add: mult_mono) lemma mult_less_mono1: "i 🚫==> 0 🚫==> i * k 🚫 * k" for i j k :: nat by (simp add: mult_strict_right_mono) text ‹Differs from the standard ‹zero_less_mult_iff›in that there are no negative numbers.› lemma nat_0_less_mult_iff [simp]: "0 🚫 * n ⟷ 0 🚫∧ 0 🚫" for m n :: nat proof (induct m) case 0 then show ?case by simp next case (Suc m) then show ?case by (cases n) simp_all qed lemma one_le_mult_iff [simp]: "Suc 0 ≤ m * n ⟷ Suc 0 ≤ m ∧ Suc 0 ≤ n" proof (induct m) case 0 then show ?case by simp next case (Suc m) then show ?case by (cases n) simp_all qed lemma mult_less_cancel2 [simp]: "m * k 🚫 * k ⟷ 0 🚫∧ m 🚫" for k m n :: nat proof (intro iffI conjI) assume m: "m * k 🚫 * k" then show "0 🚫" by (cases k) auto show "m 🚫" proof (cases k) case 0 then show ?thesis using m by auto next case (Suc k') then show ?thesis using m by (simp flip: linorder_not_le) (blast intro: add_mono mult_le_mono1) qed next assume "0 🚫∧ m 🚫" then show "m * k 🚫 * k" by (blast intro: mult_less_mono1) qed lemma mult_less_cancel1 [simp]: "k * m 🚫 * n ⟷ 0 🚫∧ m 🚫" for k m n :: nat by (simp add: mult.commute [of k]) lemma mult_le_cancel1 [simp]: "k * m ≤ k * n ⟷ (0 🚫⟶ m ≤ n)" for k m n :: nat by (simp add: linorder_not_less [symmetric], auto) lemma mult_le_cancel2 [simp]: "m * k ≤ n * k ⟷ (0 🚫⟶ m ≤ n)" for k m n :: nat by (simp add: linorder_not_less [symmetric], auto) lemma Suc_mult_less_cancel1: "Suc k * m 🚫 k * n ⟷ m 🚫" by (subst mult_less_cancel1) simp lemma Suc_mult_le_cancel1: "Suc k * m ≤ Suc k * n ⟷ m ≤ n" by (subst mult_le_cancel1) simp lemma le_square: "m ≤ m * m" for m :: nat by (cases m) (auto intro: le_add1) lemma le_cube: "m ≤ m * (m * m)" for m :: nat by (cases m) (auto intro: le_add1) text ‹Lemma for ‹gcd›\› lemma mult_eq_self_implies_10: fixes m n :: nat assumes "m = m * n" shows "n = 1 ∨ m = 0" proof (rule disjCI) assume "m ≠ 0" show "n = 1" proof (cases n "1::nat" rule: linorder_cases) case greater show ?thesis using assms mult_less_mono2 [OF greater, of m] ‹m ≠ 0›by auto qed (use assms ‹m ≠ 0›in auto) qed lemma mono_times_nat: fixes n :: nat assumes "n > 0" shows "mono (times n)" proof fix m q :: nat assume "m ≤ q" with assms show "n * m ≤ n * q" by simp qed text ‹The lattice order on 🍋‹nat›.› instantiation nat :: distrib_lattice begin definition "(inf :: nat ==> nat ==> nat) = min" definition "(sup :: nat ==> nat ==> nat) = max" instance by intro_classes (auto simp add: inf_nat_def sup_nat_def max_def not_le min_def intro: order_less_imp_le antisym elim!: order_trans order_less_trans) end subsection ‹Natural operation of natural numbers on functions› text ‹ We use the same logical constant for the power operations on functions and relations, in order to share the same syntax. › consts compow :: "nat ==> 'a ==> 'a" abbreviation compower :: "'a ==> nat ==> 'a" (infixr ‹^^›80) where "f ^^ n ≡ compow n f" notation (latex output) compower (‹(_🪙_🪙)›[1000] 1000) text ‹‹f ^^ n = f ∘…∘ f›, the ‹n›-fold composition of ‹f›\› overloading funpow ≡ "compow :: nat ==> ('a ==> 'a) ==> ('a ==> 'a)" begin primrec funpow :: "nat ==> ('a ==> 'a) ==> 'a ==> 'a" where "funpow 0 f = id" | "funpow (Suc n) f = f ∘ funpow n f" end lemma funpow_0 [simp]: "(f ^^ 0) x = x" by simp lemma funpow_Suc_right: "f ^^ Suc n = f ^^ n ∘ f" proof (induct n) case 0 then show ?case by simp next fix n assume "f ^^ Suc n = f ^^ n ∘ f" then show "f ^^ Suc (Suc n) = f ^^ Suc n ∘ f" by (simp add: o_assoc) qed lemmas funpow_simps_right = funpow.simps(1) funpow_Suc_right text ‹For code generation.› context begin qualified definition funpow :: "nat ==> ('a ==> 'a) ==> 'a ==> 'a" where funpow_code_def [code_abbrev]: "funpow = compow" lemma [code]: "funpow 0 f = id" "funpow (Suc n) f = f ∘ funpow n f" by (simp_all add: funpow_code_def) end lemma funpow_add: "f ^^ (m + n) = f ^^ m ∘ f ^^ n" by (induct m) simp_all lemma funpow_mult: "(f ^^ m) ^^ n = f ^^ (m * n)" for f :: "'a ==> 'a" by (induct n) (simp_all add: funpow_add) lemma funpow_swap1: "f ((f ^^ n) x) = (f ^^ n) (f x)" proof - have "f ((f ^^ n) x) = (f ^^ (n + 1)) x" by simp also have "… = (f ^^ n ∘ f ^^ 1) x" by (simp only: funpow_add) also have "… = (f ^^ n) (f x)" by simp finally show ?thesis . qed lemma comp_funpow: "comp f ^^ n = comp (f ^^ n)" for f :: "'a ==> 'a" by (induct n) simp_all lemma Suc_funpow[simp]: "Suc ^^ n = ((+) n)" by (induct n) simp_all lemma id_funpow[simp]: "id ^^ n = id" by (induct n) simp_all lemma funpow_mono: "mono f ==> A ≤ B ==> (f ^^ n) A ≤ (f ^^ n) B" for f :: "'a ==> ('a::order)" by (induct n) (auto simp: mono_def) lemma funpow_mono2: assumes "mono f" and "i ≤ j" and "x ≤ y" and "x ≤ f x" shows "(f ^^ i) x ≤ (f ^^ j) y" using assms(2,3) proof (induct j arbitrary: y) case 0 then show ?case by simp next case (Suc j) show ?case proof(cases "i = Suc j") case True with assms(1) Suc show ?thesis by (simp del: funpow.simps add: funpow_simps_right monoD funpow_mono) next case False with assms(1,4) Suc show ?thesis by (simp del: funpow.simps add: funpow_simps_right le_eq_less_or_eq less_Suc_eq_le) (simp add: Suc.hyps monoD order_subst1) qed qed lemma inj_fn[simp]: fixes f::"'a ==> 'a" assumes "inj f" shows "inj (f^^n)" proof (induction n) case Suc thus ?case using inj_compose[OF assms Suc.IH] by (simp del: comp_apply) qed simp lemma surj_fn[simp]: fixes f::"'a ==> 'a" assumes "surj f" shows "surj (f^^n)" proof (induction n) case Suc thus ?case by (simp add: comp_surj[OF Suc.IH assms] del: comp_apply) qed simp lemma bij_fn[simp]: fixes f::"'a ==> 'a" assumes "bij f" shows "bij (f^^n)" by (rule bijI[OF inj_fn[OF bij_is_inj[OF assms]] surj_fn[OF bij_is_surj[OF assms]]]) lemma bij_betw_funpow: 🍋‹contributor ‹Lars Noschinski›\› assumes "bij_betw f S S" shows "bij_betw (f ^^ n) S S" proof (induct n) case 0 then show ?case by (auto simp: id_def[symmetric]) next case (Suc n) then show ?case unfolding funpow.simps using assms by (rule bij_betw_trans) qed subsection ‹Kleene iteration› lemma Kleene_iter_lpfp: fixes f :: "'a::order_bot ==> 'a" assumes "mono f" and "f p ≤ p" shows "(f ^^ k) bot ≤ p" proof (induct k) case 0 show ?case by simp next case Suc show ?case using monoD[OF assms(1) Suc] assms(2) by simp qed lemma lfp_Kleene_iter: assumes "mono f" and "(f ^^ Suc k) bot = (f ^^ k) bot" shows "lfp f = (f ^^ k) bot" proof (rule antisym) show "lfp f ≤ (f ^^ k) bot" proof (rule lfp_lowerbound) show "f ((f ^^ k) bot) ≤ (f ^^ k) bot" using assms(2) by simp qed show "(f ^^ k) bot ≤ lfp f" using Kleene_iter_lpfp[OF assms(1)] lfp_unfold[OF assms(1)] by simp qed lemma mono_pow: "mono f ==> mono (f ^^ n)" for f :: "'a ==> 'a::order" by (induct n) (auto simp: mono_def) lemma lfp_funpow: assumes f: "mono f" shows "lfp (f ^^ Suc n) = lfp f" proof (rule antisym) show "lfp f ≤ lfp (f ^^ Suc n)" proof (rule lfp_lowerbound) have "f (lfp (f ^^ Suc n)) = lfp (λx. f ((f ^^ n) x))" unfolding funpow_Suc_right by (simp add: lfp_rolling f mono_pow comp_def) then show "f (lfp (f ^^ Suc n)) ≤ lfp (f ^^ Suc n)" by (simp add: comp_def) qed have "(f ^^ n) (lfp f) = lfp f" for n by (induct n) (auto intro: f lfp_fixpoint) then show "lfp (f ^^ Suc n) ≤ lfp f" by (intro lfp_lowerbound) (simp del: funpow.simps) qed lemma gfp_funpow: assumes f: "mono f" shows "gfp (f ^^ Suc n) = gfp f" proof (rule antisym) show "gfp f ≥ gfp (f ^^ Suc n)" proof (rule gfp_upperbound) have "f (gfp (f ^^ Suc n)) = gfp (λx. f ((f ^^ n) x))" unfolding funpow_Suc_right by (simp add: gfp_rolling f mono_pow comp_def) then show "f (gfp (f ^^ Suc n)) ≥ gfp (f ^^ Suc n)" by (simp add: comp_def) qed have "(f ^^ n) (gfp f) = gfp f" for n by (induct n) (auto intro: f gfp_fixpoint) then show "gfp (f ^^ Suc n) ≥ gfp f" by (intro gfp_upperbound) (simp del: funpow.simps) qed lemma Kleene_iter_gpfp: fixes f :: "'a::order_top ==> 'a" assumes "mono f" and "p ≤ f p" shows "p ≤ (f ^^ k) top" proof (induct k) case 0 show ?case by simp next case Suc show ?case using monoD[OF assms(1) Suc] assms(2) by simp qed lemma gfp_Kleene_iter: assumes "mono f" and "(f ^^ Suc k) top = (f ^^ k) top" shows "gfp f = (f ^^ k) top" (is "?lhs = ?rhs") proof (rule antisym) have "?rhs ≤ f ?rhs" using assms(2) by simp then show "?rhs ≤ ?lhs" by (rule gfp_upperbound) show "?lhs ≤ ?rhs" using Kleene_iter_gpfp[OF assms(1)] gfp_unfold[OF assms(1)] by simp qed subsection ‹Embedding of the naturals into any ‹semiring_1›:🍋‹of_nat›\› context semiring_1 begin definition of_nat :: "nat ==> 'a" where "of_nat n = (plus 1 ^^ n) 0" lemma of_nat_simps [simp]: shows of_nat_0: "of_nat 0 = 0" and of_nat_Suc: "of_nat (Suc m) = 1 + of_nat m" by (simp_all add: of_nat_def) lemma of_nat_1 [simp]: "of_nat 1 = 1" by (simp add: of_nat_def) lemma of_nat_add [simp]: "of_nat (m + n) = of_nat m + of_nat n" by (induct m) (simp_all add: ac_simps) lemma of_nat_mult [simp]: "of_nat (m * n) = of_nat m * of_nat n" by (induct m) (simp_all add: ac_simps distrib_right) lemma mult_of_nat_commute: "of_nat x * y = y * of_nat x" by (induct x) (simp_all add: algebra_simps) primrec of_nat_aux :: "('a ==> 'a) ==> nat ==> 'a ==> 'a" where "of_nat_aux inc 0 i = i" | "of_nat_aux inc (Suc n) i = of_nat_aux inc n (inc i)" 🍋‹tail recursive› lemma of_nat_code: "of_nat n = of_nat_aux (λi. i + 1) n 0" proof (induct n) case 0 then show ?case by simp next case (Suc n) have "∧i. of_nat_aux (λi. i + 1) n (i + 1) = of_nat_aux (λi. i + 1) n i + 1" by (induct n) simp_all from this [of 0] have "of_nat_aux (λi. i + 1) n 1 = of_nat_aux (λi. i + 1) n 0 + 1" by simp with Suc show ?case by (simp add: add.commute) qed lemma of_nat_of_bool [simp]: "of_nat (of_bool P) = of_bool P" by auto end declare of_nat_code [code] context semiring_1_cancel begin lemma of_nat_diff [simp]: ‹of_nat (m - n) = of_nat m - of_nat n›if ‹n ≤ m› proof - from that obtain q where ‹m = n + q› by (blast dest: le_Suc_ex) then show ?thesis by simp qed lemma of_nat_diff_if: ‹of_nat (m - n) = (if n≤m then of_nat m - of_nat n else 0)› by (simp add: not_le less_imp_le) end text ‹Class for unital semirings with characteristic zero. Includes non-ordered rings like the complex numbers.› class semiring_char_0 = semiring_1 + assumes inj_of_nat: "inj of_nat" begin lemma of_nat_eq_iff [simp]: "of_nat m = of_nat n ⟷ m = n" by (auto intro: inj_of_nat injD) text ‹Special cases where either operand is zero› lemma of_nat_0_eq_iff [simp]: "0 = of_nat n ⟷ 0 = n" by (fact of_nat_eq_iff [of 0 n, unfolded of_nat_0]) lemma of_nat_eq_0_iff [simp]: "of_nat m = 0 ⟷ m = 0" by (fact of_nat_eq_iff [of m 0, unfolded of_nat_0]) lemma of_nat_1_eq_iff [simp]: "1 = of_nat n ⟷ n=1" using of_nat_eq_iff by fastforce lemma of_nat_eq_1_iff [simp]: "of_nat n = 1 ⟷ n=1" using of_nat_eq_iff by fastforce lemma of_nat_neq_0 [simp]: "of_nat (Suc n) ≠ 0" unfolding of_nat_eq_0_iff by simp lemma of_nat_0_neq [simp]: "0 ≠ of_nat (Suc n)" unfolding of_nat_0_eq_iff by simp end class ring_char_0 = ring_1 + semiring_char_0 lemma (in ordered_semiring_1) of_nat_0_le_iff [simp]: "0 ≤ of_nat n" by (induct n) simp_all context linordered_nonzero_semiring begin lemma of_nat_less_0_iff [simp]: "¬ of_nat m 🚫" by (simp add: not_less) lemma of_nat_mono[simp]: "i ≤ j ==> of_nat i ≤ of_nat j" by (auto simp: le_iff_add intro!: add_increasing2) lemma of_nat_less_iff [simp]: "of_nat m 🚫 n ⟷ m 🚫" proof(induct m n rule: diff_induct) case (1 m) then show ?case by auto next case (2 n) then show ?case by (simp add: add_pos_nonneg) next case (3 m n) then show ?case by (auto simp: add_commute [of 1] add_mono1 not_less add_right_mono leD) qed lemma of_nat_le_iff [simp]: "of_nat m ≤ of_nat n ⟷ m ≤ n" by (simp add: not_less [symmetric] linorder_not_less [symmetric]) lemma less_imp_of_nat_less: "m 🚫==> of_nat m 🚫 n" by simp lemma of_nat_less_imp_less: "of_nat m 🚫 n ==> m 🚫" by simp text ‹Every ‹linordered_nonzero_semiring›has characteristic zero.› subclass semiring_char_0 by standard (auto intro!: injI simp add: order.eq_iff) text ‹Special cases where either operand is zero› lemma of_nat_le_0_iff [simp]: "of_nat m ≤ 0 ⟷ m = 0" by (rule of_nat_le_iff [of _ 0, simplified]) lemma of_nat_0_less_iff [simp]: "0 🚫 n ⟷ 0 🚫" by (rule of_nat_less_iff [of 0, simplified]) end context linordered_nonzero_semiring begin lemma of_nat_max: "of_nat (max x y) = max (of_nat x) (of_nat y)" by (auto simp: max_def ord_class.max_def) lemma of_nat_min: "of_nat (min x y) = min (of_nat x) (of_nat y)" by (auto simp: min_def ord_class.min_def) end context linordered_semidom begin subclass linordered_nonzero_semiring .. subclass semiring_char_0 .. end context linordered_idom begin lemma abs_of_nat [simp]: "∣of_nat n∣ = of_nat n" by (simp add: abs_if) lemma sgn_of_nat [simp]: "sgn (of_nat n) = of_bool (n > 0)" by simp end lemma of_nat_id [simp]: "of_nat n = n" by (induct n) simp_all lemma of_nat_eq_id [simp]: "of_nat = id" by (auto simp add: fun_eq_iff) subsection ‹The set of natural numbers› context semiring_1 begin definition Nats :: "'a set" (‹ℕ›) where "ℕ = range of_nat" lemma of_nat_in_Nats [simp]: "of_nat n ∈ℕ" by (simp add: Nats_def) lemma Nats_0 [simp]: "0 ∈ℕ" using of_nat_0 [symmetric] unfolding Nats_def by (rule range_eqI) lemma Nats_1 [simp]: "1 ∈ℕ" using of_nat_1 [symmetric] unfolding Nats_def by (rule range_eqI) lemma Nats_add [simp]: "a ∈ℕ==> b ∈ℕ==> a + b ∈ℕ" unfolding Nats_def using of_nat_add [symmetric] by (blast intro: range_eqI) lemma Nats_mult [simp]: "a ∈ℕ==> b ∈ℕ==> a * b ∈ℕ" unfolding Nats_def using of_nat_mult [symmetric] by (blast intro: range_eqI) lemma Nats_cases [cases set: Nats]: assumes "x ∈ℕ" obtains (of_nat) n where "x = of_nat n" unfolding Nats_def proof - from ‹x ∈ℕ›have "x ∈ range of_nat" unfolding Nats_def . then obtain n where "x = of_nat n" .. then show thesis .. qed lemma Nats_induct [case_names of_nat, induct set: Nats]: "x ∈ℕ==> (∧n. P (of_nat n)) ==> P x" by (rule Nats_cases) auto lemma Nats_nonempty [simp]: "ℕ≠ {}" unfolding Nats_def by auto end lemma Nats_diff [simp]: fixes a:: "'a::linordered_idom" assumes "a ∈ℕ" "b ∈ℕ" "b ≤ a" shows "a - b ∈ℕ" proof - obtain i where i: "a = of_nat i" using Nats_cases assms by blast obtain j where j: "b = of_nat j" using Nats_cases assms by blast have "j ≤ i" using ‹b ≤ a›i j of_nat_le_iff by blast then have *: "of_nat i - of_nat j = (of_nat (i-j) :: 'a)" by (simp add: of_nat_diff) then show ?thesis by (simp add: * i j) qed subsection ‹Further arithmetic facts concerning the natural numbers› lemma subst_equals: assumes "t = s" and "u = t" shows "u = s" using assms(2,1) by (rule trans) locale nat_arith begin lemma add1: "(A::'a::comm_monoid_add) ≡ k + a ==> A + b ≡ k + (a + b)" by (simp only: ac_simps) lemma add2: "(B::'a::comm_monoid_add) ≡ k + b ==> a + B ≡ k + (a + b)" by (simp only: ac_simps) lemma suc1: "A == k + a ==> Suc A ≡ k + Suc a" by (simp only: add_Suc_right) lemma rule0: "(a::'a::comm_monoid_add) ≡ a + 0" by (simp only: add_0_right) end ML_file ‹Tools/nat_arith.ML› simproc_setup nateq_cancel_sums ("(l::nat) + m = n" | "(l::nat) = m + n" | "Suc m = n" | "m = Suc n") = ‹K (try o Nat_Arith.cancel_eq_conv)› simproc_setup natless_cancel_sums ("(l::nat) + m 🚫" | "(l::nat) 🚫 + n" | "Suc m 🚫" | "m 🚫 n") = ‹K (try o Nat_Arith.cancel_less_conv)› simproc_setup natle_cancel_sums ("(l::nat) + m ≤ n" | "(l::nat) ≤ m + n" | "Suc m ≤ n" | "m ≤ Suc n") = ‹K (try o Nat_Arith.cancel_le_conv)› simproc_setup natdiff_cancel_sums ("(l::nat) + m - n" | "(l::nat) - (m + n)" | "Suc m - n" | "m - Suc n") = ‹K (try o Nat_Arith.cancel_diff_conv)› context preorder begin lemma lift_Suc_mono_le: assumes mono: "∧n. f n ≤ f (Suc n)" and "n ≤ n'" shows "f n ≤ f n'" proof (cases "n 🚫'") case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono order.trans) next case False with ‹n ≤ n'›show ?thesis by auto qed lemma lift_Suc_antimono_le: assumes mono: "∧n. f n ≥ f (Suc n)" and "n ≤ n'" shows "f n ≥ f n'" proof (cases "n 🚫'") case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono order.trans) next case False with ‹n ≤ n'›show ?thesis by auto qed lemma lift_Suc_mono_less: assumes mono: "∧n. f n 🚫 (Suc n)" and "n 🚫'" shows "f n 🚫 n'" using ‹n 🚫'›by (induct n n' rule: less_Suc_induct) (auto intro: mono order.strict_trans) lemma lift_Suc_mono_less_iff: "(∧n. f n 🚫 (Suc n)) ==> f n 🚫 m ⟷ n 🚫" by (blast intro: less_asym' lift_Suc_mono_less [of f] dest: linorder_not_less[THEN iffD1] le_eq_less_or_eq [THEN iffD1]) end lemma mono_iff_le_Suc: "mono f ⟷ (∀n. f n ≤ f (Suc n))" unfolding mono_def by (auto intro: lift_Suc_mono_le [of f]) lemma antimono_iff_le_Suc: "antimono f ⟷ (∀n. f (Suc n) ≤ f n)" unfolding antimono_def by (auto intro: lift_Suc_antimono_le [of f]) lemma strict_mono_Suc_iff: "strict_mono f ⟷ (∀n. f n 🚫 (Suc n))" proof (intro iffI strict_monoI) assume *: "∀n. f n 🚫 (Suc n)" fix m n :: nat assume "m 🚫" thus "f m 🚫 n" by (induction rule: less_Suc_induct) (use * in auto) qed (auto simp: strict_mono_def) lemma strict_mono_add: "strict_mono (λn::'a::linordered_semidom. n + k)" by (auto simp: strict_mono_def) lemma mono_nat_linear_lb: fixes f :: "nat ==> nat" assumes "∧m n. m 🚫==> f m 🚫 n" shows "f m + k ≤ f (m + k)" proof (induct k) case 0 then show ?case by simp next case (Suc k) then have "Suc (f m + k) ≤ Suc (f (m + k))" by simp also from assms [of "m + k" "Suc (m + k)"] have "Suc (f (m + k)) ≤ f (Suc (m + k))" by (simp add: Suc_le_eq) finally show ?case by simp qed lemma bex_const1_if_mono_below_diag: fixes f :: "nat ==> nat" assumes "mono f" shows "f n 🚫==>∃i🚫 f(Suc i) = f i" proof(induction n) case 0 then show ?case by simp next case (Suc n) have *: "f n ≤ f(Suc n)" using assms[simplified mono_iff_le_Suc] by blast from Suc.prems[simplified less_Suc_eq] show ?case proof assume "f(Suc n) 🚫" from order.strict_trans1[OF * this] show ?thesis using Suc.IH less_SucI by blast next assume "f(Suc n) = n" from order.strict_trans1[OF * Suc.prems, simplified less_Suc_eq] show ?case proof assume "f n 🚫" thus ?thesis using Suc.IH less_SucI by blast next assume "f n = n" with ‹f(Suc n) = n›show ?thesis by auto qed qed qed lemma bex_const1_if_mono_below_diag_Suc: fixes f :: "nat ==> nat" assumes "mono f" "f(Suc m) ≤ m" shows "∃i≤m. f (Suc i) = f i" using bex_const1_if_mono_below_diag[OF assms(1), of "Suc m"] assms(2) less_Suc_eq_le by blast text ‹Subtraction laws, mostly by Clemens Ballarin› lemma diff_less_mono: fixes a b c :: nat assumes "a 🚫" and "c ≤ a" shows "a - c 🚫 - c" proof - from assms obtain d e where "b = c + (d + e)" and "a = c + e" and "d > 0" by (auto dest!: le_Suc_ex less_imp_Suc_add simp add: ac_simps) then show ?thesis by simp qed lemma less_diff_conv: "i 🚫 - k ⟷ i + k 🚫" for i j k :: nat by (cases "k ≤ j") (auto simp add: not_le dest: less_imp_Suc_add le_Suc_ex) lemma less_diff_conv2: "k ≤ j ==> j - k 🚫⟷ j 🚫 + k" for j k i :: nat by (auto dest: le_Suc_ex) lemma le_diff_conv: "j - k ≤ i ⟷ j ≤ i + k" for j k i :: nat by (cases "k ≤ j") (auto simp add: not_le dest!: less_imp_Suc_add le_Suc_ex) lemma diff_diff_cancel [simp]: "i ≤ n ==> n - (n - i) = i" for i n :: nat by (auto dest: le_Suc_ex) lemma diff_less [simp]: "0 🚫==> 0 🚫==> m - n 🚫" for i n :: nat by (auto dest: less_imp_Suc_add) text ‹Simplification of relational expressions involving subtraction› lemma diff_diff_eq: "k ≤ m ==> k ≤ n ==> m - k - (n - k) = m - n" for m n k :: nat by (auto dest!: le_Suc_ex) hide_fact (open) diff_diff_eq lemma eq_diff_iff: "k ≤ m ==> k ≤ n ==> m - k = n - k ⟷ m = n" for m n k :: nat by (auto dest: le_Suc_ex) lemma less_diff_iff: "k ≤ m ==> k ≤ n ==> m - k 🚫 - k ⟷ m 🚫" for m n k :: nat by (auto dest!: le_Suc_ex) lemma le_diff_iff: "k ≤ m ==> k ≤ n ==> m - k ≤ n - k ⟷ m ≤ n" for m n k :: nat by (auto dest!: le_Suc_ex) lemma le_diff_iff': "a ≤ c ==> b ≤ c ==> c - a ≤ c - b ⟷ b ≤ a" for a b c :: nat by (force dest: le_Suc_ex) text ‹(Anti)Monotonicity of subtraction -- by Stephan Merz› lemma diff_le_mono: "m ≤ n ==> m - l ≤ n - l" for m n l :: nat by (auto dest: less_imp_le less_imp_Suc_add split: nat_diff_split) lemma diff_le_mono2: "m ≤ n ==> l - n ≤ l - m" for m n l :: nat by (auto dest: less_imp_le le_Suc_ex less_imp_Suc_add less_le_trans split: nat_diff_split) lemma diff_less_mono2: "m 🚫==> m 🚫==> l - n 🚫 - m" for m n l :: nat by (auto dest: less_imp_Suc_add split: nat_diff_split) lemma diffs0_imp_equal: "m - n = 0 ==> n - m = 0 ==> m = n" for m n :: nat by (simp split: nat_diff_split) lemma min_diff: "min (m - i) (n - i) = min m n - i" for m n i :: nat by (cases m n rule: le_cases) (auto simp add: not_le min.absorb1 min.absorb2 min.absorb_iff1 [symmetric] diff_le_mono) lemma inj_on_diff_nat: fixes k :: nat assumes "∧n. n ∈ N ==> k ≤ n" shows "inj_on (λn. n - k) N" proof (rule inj_onI) fix x y assume a: "x ∈ N" "y ∈ N" "x - k = y - k" with assms have "x - k + k = y - k + k" by auto with a assms show "x = y" by (auto simp add: eq_diff_iff) qed text ‹Rewriting to pull differences out› lemma diff_diff_right [simp]: "k ≤ j ==> i - (j - k) = i + k - j" for i j k :: nat by (fact diff_diff_right) lemma diff_Suc_diff_eq1 [simp]: assumes "k ≤ j" shows "i - Suc (j - k) = i + k - Suc j" proof - from assms have *: "Suc (j - k) = Suc j - k" by (simp add: Suc_diff_le) from assms have "k ≤ Suc j" by (rule order_trans) simp with diff_diff_right [of k "Suc j" i] * show ?thesis by simp qed lemma diff_Suc_diff_eq2 [simp]: assumes "k ≤ j" shows "Suc (j - k) - i = Suc j - (k + i)" proof - from assms obtain n where "j = k + n" by (auto dest: le_Suc_ex) moreover have "Suc n - i = (k + Suc n) - (k + i)" using add_diff_cancel_left [of k "Suc n" i] by simp ultimately show ?thesis by simp qed lemma Suc_diff_Suc: assumes "n 🚫" shows "Suc (m - Suc n) = m - n" proof - from assms obtain q where "m = n + Suc q" by (auto dest: less_imp_Suc_add) moreover define r where "r = Suc q" ultimately have "Suc (m - Suc n) = r" and "m = n + r" by simp_all then show ?thesis by simp qed lemma one_less_mult: "Suc 0 🚫==> Suc 0 🚫==> Suc 0 🚫 * n" using less_1_mult [of n m] by (simp add: ac_simps) lemma n_less_m_mult_n: "0 🚫==> Suc 0 🚫==> n 🚫 * n" using mult_strict_right_mono [of 1 m n] by simp lemma n_less_n_mult_m: "0 🚫==> Suc 0 🚫==> n 🚫 * m" using mult_strict_left_mono [of 1 m n] by simp text ‹Induction starting beyond zero› lemma nat_induct_at_least [consumes 1, case_names base Suc]: "P n" if "n ≥ m" "P m" "∧n. n ≥ m ==> P n ==> P (Suc n)" proof - define q where "q = n - m" with ‹n ≥ m›have "n = m + q" by simp moreover have "P (m + q)" by (induction q) (use that in simp_all) ultimately show "P n" by simp qed lemma nat_induct_non_zero [consumes 1, case_names 1 Suc]: "P n" if "n > 0" "P 1" "∧n. n > 0 ==> P n ==> P (Suc n)" proof - from ‹n > 0›have "n ≥ 1" by (cases n) simp_all moreover note ‹P 1› moreover have "∧n. n ≥ 1 ==> P n ==> P (Suc n)" using ‹∧n. n > 0 ==> P n ==> P (Suc n)› by (simp add: Suc_le_eq) ultimately show "P n" by (rule nat_induct_at_least) qed text ‹Specialized induction principles that work "backwards":› lemma inc_induct [consumes 1, case_names base step]: assumes less: "i ≤ j" and base: "P j" and step: "∧n. i ≤ n ==> n 🚫==> P (Suc n) ==> P n" shows "P i" using less step proof (induct "j - i" arbitrary: i) case (0 i) then have "i = j" by simp with base show ?case by simp next case (Suc d n) from Suc.hyps have "n ≠ j" by auto with Suc have "n 🚫" by (simp add: less_le) from ‹Suc d = j - n›have "d + 1 = j - n" by simp then have "d + 1 - 1 = j - n - 1" by simp then have "d = j - n - 1" by simp then have "d = j - (n + 1)" by (simp add: diff_diff_eq) then have "d = j - Suc n" by simp moreover from ‹n 🚫›have "Suc n ≤ j" by (simp add: Suc_le_eq) ultimately have "P (Suc n)" proof (rule Suc.hyps) fix q assume "Suc n ≤ q" then have "n ≤ q" by (simp add: Suc_le_eq less_imp_le) moreover assume "q 🚫" moreover assume "P (Suc q)" ultimately show "P q" by (rule Suc.prems) qed with order_refl ‹n 🚫›show "P n" by (rule Suc.prems) qed lemma strict_inc_induct [consumes 1, case_names base step]: assumes less: "i 🚫" and base: "∧i. j = Suc i ==> P i" and step: "∧i. Suc i 🚫==> P (Suc i) ==> P i" shows "P i" using less proof (induct "j - i - 1" arbitrary: i) case (0 i) from ‹i 🚫›obtain n where "j = i + n" and "n > 0" by (auto dest!: less_imp_Suc_add) with 0 have "j = Suc i" by (auto intro: order_antisym simp add: Suc_le_eq) with base show ?case by simp next case (Suc d i) from ‹Suc d = j - i - 1›have *: "Suc d = j - Suc i" by (simp add: diff_diff_add) then have "Suc d - 1 = j - Suc i - 1" by simp then have "d = j - Suc i - 1" by simp moreover from * have "j - Suc i ≠ 0" by auto then have "Suc i 🚫" by (simp add: not_le) ultimately have "P (Suc i)" by (rule Suc.hyps) with ‹Suc i 🚫›show "P i" by (rule step) qed lemma zero_induct_lemma: "P k ==> (∧n. P (Suc n) ==> P n) ==> P (k - i)" using inc_induct[of "k - i" k P, simplified] by blast lemma zero_induct: "P k ==> (∧n. P (Suc n) ==> P n) ==> P 0" using inc_induct[of 0 k P] by blast text ‹Further induction rule similar to @{thm inc_induct}.› lemma dec_induct [consumes 1, case_names base step]: "i ≤ j ==> P i ==> (∧n. i ≤ n ==> n 🚫==> P n ==> P (Suc n)) ==> P j" proof (induct j arbitrary: i) case 0 then show ?case by simp next case (Suc j) from Suc.prems consider "i ≤ j" | "i = Suc j" by (auto simp add: le_Suc_eq) then show ?case proof cases case 1 moreover have "j 🚫 j" by simp moreover have "P j" using ‹i ≤ j›‹P i› proof (rule Suc.hyps) fix q assume "i ≤ q" moreover assume "q 🚫" then have "q 🚫 j" by (simp add: less_Suc_eq) moreover assume "P q" ultimately show "P (Suc q)" by (rule Suc.prems) qed ultimately show "P (Suc j)" by (rule Suc.prems) next case 2 with ‹P i›show "P (Suc j)" by simp qed qed lemma transitive_stepwise_le: assumes "m ≤ n" "∧x. R x x" "∧x y z. R x y ==> R y z ==> R x z" and "∧n. R n (Suc n)" shows "R m n" using ‹m ≤ n› by (induction rule: dec_induct) (use assms in blast)+ subsubsection ‹Greatest operator› lemma ex_has_greatest_nat: "P (k::nat) ==>∀y. P y ⟶ y ≤ b ==>∃x. P x ∧ (∀y. P y ⟶ y ≤ x)" proof (induction "b-k" arbitrary: b k rule: less_induct) case less show ?case proof cases assume "∃n>k. P n" then obtain n where "n>k" "P n" by blast have "n ≤ b" using ‹P n›less.prems(2) by auto hence "b-n 🚫" by(rule diff_less_mono2[OF ‹k🚫›less_le_trans[OF ‹k🚫›]]) from less.hyps[OF this ‹P n›less.prems(2)] show ?thesis . next assume "¬ (∃n>k. P n)" hence "∀y. P y ⟶ y ≤ k" by (auto simp: not_less) thus ?thesis using less.prems(1) by auto qed qed lemma fixes k::nat assumes "P k" and minor: "∧y. P y ==> y ≤ b" shows GreatestI_nat: "P (Greatest P)" and Greatest_le_nat: "k ≤ Greatest P" proof - obtain x where "P x" "∧y. P y ==> y ≤ x" using assms ex_has_greatest_nat by blast with ‹P k›show "P (Greatest P)" "k ≤ Greatest P" using GreatestI2_order by blast+ qed lemma GreatestI_ex_nat: "[∃k::nat. P k; ∧y. P y ==> y ≤ b ]==> P (Greatest P)" by (blast intro: GreatestI_nat) subsection ‹Monotonicity of ‹funpow›\› lemma funpow_increasing: "m ≤ n ==> mono f ==> (f ^^ n) ⊤≤ (f ^^ m) ⊤" for f :: "'a::order_top ==> 'a" by (induct rule: inc_induct) (auto simp del: funpow.simps(2) simp add: funpow_Suc_right intro: order_trans[OF _ funpow_mono]) lemma funpow_decreasing: "m ≤ n ==> mono f ==> (f ^^ m) ⊥≤ (f ^^ n) ⊥" for f :: "'a::order_bot ==> 'a" by (induct rule: dec_induct) (auto simp del: funpow.simps(2) simp add: funpow_Suc_right intro: order_trans[OF _ funpow_mono]) lemma mono_funpow: "mono Q ==> mono (λi. (Q ^^ i) ⊥)" for Q :: "'a::order_bot ==> 'a" by (auto intro!: funpow_decreasing simp: mono_def) lemma antimono_funpow: "mono Q ==> antimono (λi. (Q ^^ i) ⊤)" for Q :: "'a::order_top ==> 'a" by (auto intro!: funpow_increasing simp: antimono_def) subsection ‹Kleene's fixed point theorem for continuous functions› text ‹Kleene's fixed point theorem shows that the ‹lfp›of a omega-continuous function can be obtained as the supremum of an omega chain. It only requires an omega-complete partial order. We prove it here for complete lattices because the latter structures are not defined in Main but the theorem is also useful for complete lattices.› definition omega_chain :: "(nat ==> ('a::complete_lattice)) ==> bool" where "omega_chain C = (∀i. C i ≤ C(Suc i))" definition omega_cont :: "(('a::complete_lattice) ==> ('b::complete_lattice)) ==> bool" where "omega_cont f = (∀C. omega_chain C ⟶ f(SUP n. C n) = (SUP n. f(C n)))" lemma omega_chain_mono: "omega_chain C ==> i ≤ j ==> C i ≤ C j" unfolding omega_chain_def using lift_Suc_mono_le[of C] by(induction "j-i" arbitrary: i j)auto lemma mono_if_omega_cont: fixes f :: "('a::complete_lattice) ==> ('b::complete_lattice)" assumes "omega_cont f" shows "mono f" proof fix a b :: "'a" assume "a ≤ b" let ?C = "λn::nat. if n=0 then a else b" have *: "omega_chain ?C" using ‹a ≤ b›by(auto simp: omega_chain_def) have "f a ≤ sup (f a) (SUP n. f(?C n))" by(rule sup.cobounded1) also have "… = sup (f(?C 0)) (SUP n. f(?C n))" by (simp) also have "… = (SUP n. f (?C n))" using SUP_absorb[OF UNIV_I] . also have "… = f (SUP n. ?C n)" using assms * by (simp add: omega_cont_def del: if_image_distrib) also have "f (SUP n. ?C n) = f b" using ‹a ≤ b›by (auto simp add: gt_ex sup.absorb2 split: if_splits) finally show "f a ≤ f b" . qed lemma omega_chain_iterates: fixes f :: "('a::complete_lattice) ==> 'a" assumes "mono f" shows "omega_chain(λn. (f^^n) bot)" proof- have "(f ^^ n) bot ≤ (f ^^ Suc n) bot" for n proof (induction n) case 0 show ?case by simp next case (Suc n) thus ?case using assms by (auto simp: mono_def) qed thus ?thesis by(auto simp: omega_chain_def assms) qed theorem Kleene_lfp: assumes "omega_cont f" shows "lfp f = (SUP n. (f^^n) bot)" (is "_ = ?U") proof(rule Orderings.antisym) from assms mono_if_omega_cont have mono: "(f ^^ n) bot ≤ (f ^^ Suc n) bot" for n using funpow_decreasing [of n "Suc n"] by auto show "lfp f ≤ ?U" proof (rule lfp_lowerbound) have "f ?U = (SUP n. (f^^Suc n) bot)" using omega_chain_iterates[OF mono_if_omega_cont[OF assms]] assms by(simp add: omega_cont_def) also have "… = ?U" using mono by(blast intro: SUP_eq) finally show "f ?U ≤ ?U" by simp qed next have "(f^^n) bot ≤ p" if "f p ≤ p" for n p proof - show ?thesis proof(induction n) case 0 show ?case by simp next case Suc from monoD[OF mono_if_omega_cont[OF assms] Suc] ‹f p ≤ p› show ?case by simp qed qed thus "?U ≤ lfp f" using lfp_unfold[OF mono_if_omega_cont[OF assms]] by (simp add: SUP_le_iff) qed subsection ‹The divides relation on 🍋‹nat›\› lemma dvd_1_left [iff]: "Suc 0 dvd k" by (simp add: dvd_def) lemma dvd_1_iff_1 [simp]: "m dvd Suc 0 ⟷ m = Suc 0" by (simp add: dvd_def) lemma nat_dvd_1_iff_1 [simp]: "m dvd 1 ⟷ m = 1" for m :: nat by (simp add: dvd_def) lemma dvd_antisym: "m dvd n ==> n dvd m ==> m = n" for m n :: nat unfolding dvd_def by (force dest: mult_eq_self_implies_10 simp add: mult.assoc) lemma dvd_diff_nat [simp]: "k dvd m ==> k dvd n ==> k dvd (m - n)" for k m n :: nat unfolding dvd_def by (blast intro: right_diff_distrib' [symmetric]) lemma dvd_diffD: fixes k m n :: nat assumes "k dvd m - n" "k dvd n" "n ≤ m" shows "k dvd m" proof - have "k dvd n + (m - n)" using assms by (blast intro: dvd_add) with assms show ?thesis by simp qed lemma dvd_diffD1: "k dvd m - n ==> k dvd m ==> n ≤ m ==> k dvd n" for k m n :: nat by (drule_tac m = m in dvd_diff_nat) auto lemma dvd_mult_cancel: fixes m n k :: nat assumes "k * m dvd k * n" and "0 🚫" shows "m dvd n" proof - from assms(1) obtain q where "k * n = (k * m) * q" .. then have "k * n = k * (m * q)" by (simp add: ac_simps) with ‹0 🚫›have "n = m * q" by (auto simp add: mult_left_cancel) then show ?thesis .. qed lemma dvd_mult_cancel1: fixes m n :: nat assumes "0 🚫" shows "m * n dvd m ⟷ n = 1" proof assume "m * n dvd m" then have "m * n dvd m * 1" by simp then have "n dvd 1" by (iprover intro: assms dvd_mult_cancel) then show "n = 1" by auto qed auto lemma dvd_mult_cancel2: "0 🚫==> n * m dvd m ⟷ n = 1" for m n :: nat using dvd_mult_cancel1 [of m n] by (simp add: ac_simps) lemma dvd_imp_le: "k dvd n ==> 0 🚫==> k ≤ n" for k n :: nat by (auto elim!: dvdE) (auto simp add: gr0_conv_Suc) lemma nat_dvd_not_less: "0 🚫==> m 🚫==>¬ n dvd m" for m n :: nat by (auto elim!: dvdE) (auto simp add: gr0_conv_Suc) lemma less_eq_dvd_minus: fixes m n :: nat assumes "m ≤ n" shows "m dvd n ⟷ m dvd n - m" proof - from assms have "n = m + (n - m)" by simp then obtain q where "n = m + q" .. then show ?thesis by (simp add: add.commute [of m]) qed lemma dvd_minus_self: "m dvd n - m ⟷ n 🚫∨ m dvd n" for m n :: nat by (cases "n 🚫") (auto elim!: dvdE simp add: not_less le_imp_diff_is_add dest: less_imp_le) lemma dvd_minus_add: fixes m n q r :: nat assumes "q ≤ n" "q ≤ r * m" shows "m dvd n - q ⟷ m dvd n + (r * m - q)" proof - have "m dvd n - q ⟷ m dvd r * m + (n - q)" using dvd_add_times_triv_left_iff [of m r] by simp also from assms have "…⟷ m dvd r * m + n - q" by simp also from assms have "…⟷ m dvd (r * m - q) + n" by simp also have "…⟷ m dvd n + (r * m - q)" by (simp add: add.commute) finally show ?thesis . qed subsection ‹Aliasses› lemma nat_mult_1: "1 * n = n" for n :: nat by (fact mult_1_left) lemma nat_mult_1_right: "n * 1 = n" for n :: nat by (fact mult_1_right) lemma diff_mult_distrib: "(m - n) * k = (m * k) - (n * k)" for k m n :: nat by (fact left_diff_distrib') lemma diff_mult_distrib2: "k * (m - n) = (k * m) - (k * n)" for k m n :: nat by (fact right_diff_distrib') (*Used in AUTO2 and Groups.le_diff_conv2 (with variables renamed) doesn't work for some reason*) lemma le_diff_conv2: "k ≤ j ==> (i ≤ j - k) = (i + k ≤ j)" for i j k :: nat by (fact le_diff_conv2)
lemma diff_self_eq_0 [simp]: "m - m = 0" for m :: nat by (fact diff_cancel)
lemma diff_diff_left [simp]: "i - j - k = i - (j + k)" for i j k :: nat by (fact diff_diff_add)
lemma diff_commute: "i - j - k = i - k - j" for i j k :: nat by (fact diff_right_commute)
lemma diff_add_inverse: "(n + m) - n = m" for m n :: nat by (fact add_diff_cancel_left')
lemma diff_add_inverse2: "(m + n) - n = m" for m n :: nat by (fact add_diff_cancel_right')
lemma diff_cancel: "(k + m) - (k + n) = m - n" for k m n :: nat by (fact add_diff_cancel_left)
lemma diff_cancel2: "(m + k) - (n + k) = m - n" for k m n :: nat by (fact add_diff_cancel_right)
lemma diff_add_0: "n - (n + m) = 0" for m n :: nat by (fact diff_add_zero)
lemma add_mult_distrib2: "k * (m + n) = (k * m) + (k * n)" for k m n :: nat by (fact distrib_left)
class size = fixes size :: "'a ==> nat"🍋‹see further theory ‹Wellfounded›\›
instantiation nat :: size begin
definition size_nat where [simp, code]: "size (n::nat) = n"
instance ..
end
lemmas size_nat = size_nat_def
lemma size_neq_size_imp_neq: "size x ≠ size y ==> x ≠ y" by (erule contrapos_nn) (rule arg_cong)
subsection‹Code module namespace›
code_identifier code_module Nat ⇀ (SML) Arith and (OCaml) Arith and (Haskell) Arith
hide_const (open) of_nat_aux
end
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.65Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-05-03)
¤
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.