diff --git a/src/HOL/Groups.thy b/src/HOL/Groups.thy --- a/src/HOL/Groups.thy +++ b/src/HOL/Groups.thy @@ -1,1500 +1,1519 @@ (* Title: HOL/Groups.thy Author: Gertrud Bauer Author: Steven Obua Author: Lawrence C Paulson Author: Markus Wenzel Author: Jeremy Avigad *) section \Groups, also combined with orderings\ theory Groups imports Orderings begin subsection \Dynamic facts\ named_theorems ac_simps "associativity and commutativity simplification rules" and algebra_simps "algebra simplification rules for rings" and algebra_split_simps "algebra simplification rules for rings, with potential goal splitting" and field_simps "algebra simplification rules for fields" and field_split_simps "algebra simplification rules for fields, with potential goal splitting" text \ The rewrites accumulated in \algebra_simps\ deal with the classical algebraic structures of groups, rings and family. They simplify terms by multiplying everything out (in case of a ring) and bringing sums and products into a canonical form (by ordered rewriting). As a result it decides group and ring equalities but also helps with inequalities. Of course it also works for fields, but it knows nothing about multiplicative inverses or division. This is catered for by \field_simps\. Facts in \field_simps\ multiply with denominators in (in)equations if they can be proved to be non-zero (for equations) or positive/negative (for inequalities). Can be too aggressive and is therefore separate from the more benign \algebra_simps\. Collections \algebra_split_simps\ and \field_split_simps\ correspond to \algebra_simps\ and \field_simps\ but contain more aggresive rules that may lead to goal splitting. \ subsection \Abstract structures\ text \ These locales provide basic structures for interpretation into bigger structures; extensions require careful thinking, otherwise undesired effects may occur due to interpretation. \ locale semigroup = fixes f :: "'a \ 'a \ 'a" (infixl "\<^bold>*" 70) assumes assoc [ac_simps]: "a \<^bold>* b \<^bold>* c = a \<^bold>* (b \<^bold>* c)" locale abel_semigroup = semigroup + assumes commute [ac_simps]: "a \<^bold>* b = b \<^bold>* a" begin lemma left_commute [ac_simps]: "b \<^bold>* (a \<^bold>* c) = a \<^bold>* (b \<^bold>* c)" proof - have "(b \<^bold>* a) \<^bold>* c = (a \<^bold>* b) \<^bold>* c" by (simp only: commute) then show ?thesis by (simp only: assoc) qed end locale monoid = semigroup + fixes z :: 'a ("\<^bold>1") assumes left_neutral [simp]: "\<^bold>1 \<^bold>* a = a" assumes right_neutral [simp]: "a \<^bold>* \<^bold>1 = a" locale comm_monoid = abel_semigroup + fixes z :: 'a ("\<^bold>1") assumes comm_neutral: "a \<^bold>* \<^bold>1 = a" begin sublocale monoid by standard (simp_all add: commute comm_neutral) end locale group = semigroup + fixes z :: 'a ("\<^bold>1") fixes inverse :: "'a \ 'a" assumes group_left_neutral: "\<^bold>1 \<^bold>* a = a" assumes left_inverse [simp]: "inverse a \<^bold>* a = \<^bold>1" begin lemma left_cancel: "a \<^bold>* b = a \<^bold>* c \ b = c" proof assume "a \<^bold>* b = a \<^bold>* c" then have "inverse a \<^bold>* (a \<^bold>* b) = inverse a \<^bold>* (a \<^bold>* c)" by simp then have "(inverse a \<^bold>* a) \<^bold>* b = (inverse a \<^bold>* a) \<^bold>* c" by (simp only: assoc) then show "b = c" by (simp add: group_left_neutral) qed simp sublocale monoid proof fix a have "inverse a \<^bold>* a = \<^bold>1" by simp then have "inverse a \<^bold>* (a \<^bold>* \<^bold>1) = inverse a \<^bold>* a" by (simp add: group_left_neutral assoc [symmetric]) with left_cancel show "a \<^bold>* \<^bold>1 = a" by (simp only: left_cancel) qed (fact group_left_neutral) lemma inverse_unique: assumes "a \<^bold>* b = \<^bold>1" shows "inverse a = b" proof - from assms have "inverse a \<^bold>* (a \<^bold>* b) = inverse a" by simp then show ?thesis by (simp add: assoc [symmetric]) qed lemma inverse_neutral [simp]: "inverse \<^bold>1 = \<^bold>1" by (rule inverse_unique) simp lemma inverse_inverse [simp]: "inverse (inverse a) = a" by (rule inverse_unique) simp lemma right_inverse [simp]: "a \<^bold>* inverse a = \<^bold>1" proof - have "a \<^bold>* inverse a = inverse (inverse a) \<^bold>* inverse a" by simp also have "\ = \<^bold>1" by (rule left_inverse) then show ?thesis by simp qed lemma inverse_distrib_swap: "inverse (a \<^bold>* b) = inverse b \<^bold>* inverse a" proof (rule inverse_unique) have "a \<^bold>* b \<^bold>* (inverse b \<^bold>* inverse a) = a \<^bold>* (b \<^bold>* inverse b) \<^bold>* inverse a" by (simp only: assoc) also have "\ = \<^bold>1" by simp finally show "a \<^bold>* b \<^bold>* (inverse b \<^bold>* inverse a) = \<^bold>1" . qed lemma right_cancel: "b \<^bold>* a = c \<^bold>* a \ b = c" proof assume "b \<^bold>* a = c \<^bold>* a" then have "b \<^bold>* a \<^bold>* inverse a= c \<^bold>* a \<^bold>* inverse a" by simp then show "b = c" by (simp add: assoc) qed simp end subsection \Generic operations\ class zero = fixes zero :: 'a ("0") class one = fixes one :: 'a ("1") hide_const (open) zero one lemma Let_0 [simp]: "Let 0 f = f 0" unfolding Let_def .. lemma Let_1 [simp]: "Let 1 f = f 1" unfolding Let_def .. setup \ Reorient_Proc.add (fn Const(\<^const_name>\Groups.zero\, _) => true | Const(\<^const_name>\Groups.one\, _) => true | _ => false) \ simproc_setup reorient_zero ("0 = x") = Reorient_Proc.proc simproc_setup reorient_one ("1 = x") = Reorient_Proc.proc typed_print_translation \ let fun tr' c = (c, fn ctxt => fn T => fn ts => if null ts andalso Printer.type_emphasis ctxt T then Syntax.const \<^syntax_const>\_constrain\ $ Syntax.const c $ Syntax_Phases.term_of_typ ctxt T else raise Match); in map tr' [\<^const_syntax>\Groups.one\, \<^const_syntax>\Groups.zero\] end \ \ \show types that are presumably too general\ class plus = fixes plus :: "'a \ 'a \ 'a" (infixl "+" 65) class minus = fixes minus :: "'a \ 'a \ 'a" (infixl "-" 65) class uminus = fixes uminus :: "'a \ 'a" ("- _" [81] 80) class times = fixes times :: "'a \ 'a \ 'a" (infixl "*" 70) subsection \Semigroups and Monoids\ class semigroup_add = plus + assumes add_assoc [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "(a + b) + c = a + (b + c)" begin sublocale add: semigroup plus by standard (fact add_assoc) end hide_fact add_assoc class ab_semigroup_add = semigroup_add + assumes add_commute [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a + b = b + a" begin sublocale add: abel_semigroup plus by standard (fact add_commute) declare add.left_commute [algebra_simps, algebra_split_simps, field_simps, field_split_simps] lemmas add_ac = add.assoc add.commute add.left_commute end hide_fact add_commute lemmas add_ac = add.assoc add.commute add.left_commute class semigroup_mult = times + assumes mult_assoc [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "(a * b) * c = a * (b * c)" begin sublocale mult: semigroup times by standard (fact mult_assoc) end hide_fact mult_assoc class ab_semigroup_mult = semigroup_mult + assumes mult_commute [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a * b = b * a" begin sublocale mult: abel_semigroup times by standard (fact mult_commute) declare mult.left_commute [algebra_simps, algebra_split_simps, field_simps, field_split_simps] lemmas mult_ac = mult.assoc mult.commute mult.left_commute end hide_fact mult_commute lemmas mult_ac = mult.assoc mult.commute mult.left_commute class monoid_add = zero + semigroup_add + assumes add_0_left: "0 + a = a" and add_0_right: "a + 0 = a" begin sublocale add: monoid plus 0 by standard (fact add_0_left add_0_right)+ end lemma zero_reorient: "0 = x \ x = 0" by (fact eq_commute) class comm_monoid_add = zero + ab_semigroup_add + assumes add_0: "0 + a = a" begin subclass monoid_add by standard (simp_all add: add_0 add.commute [of _ 0]) sublocale add: comm_monoid plus 0 by standard (simp add: ac_simps) end class monoid_mult = one + semigroup_mult + assumes mult_1_left: "1 * a = a" and mult_1_right: "a * 1 = a" begin sublocale mult: monoid times 1 by standard (fact mult_1_left mult_1_right)+ end lemma one_reorient: "1 = x \ x = 1" by (fact eq_commute) class comm_monoid_mult = one + ab_semigroup_mult + assumes mult_1: "1 * a = a" begin subclass monoid_mult by standard (simp_all add: mult_1 mult.commute [of _ 1]) sublocale mult: comm_monoid times 1 by standard (simp add: ac_simps) end class cancel_semigroup_add = semigroup_add + assumes add_left_imp_eq: "a + b = a + c \ b = c" assumes add_right_imp_eq: "b + a = c + a \ b = c" begin lemma add_left_cancel [simp]: "a + b = a + c \ b = c" by (blast dest: add_left_imp_eq) lemma add_right_cancel [simp]: "b + a = c + a \ b = c" by (blast dest: add_right_imp_eq) end class cancel_ab_semigroup_add = ab_semigroup_add + minus + assumes add_diff_cancel_left' [simp]: "(a + b) - a = b" assumes diff_diff_add [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a - b - c = a - (b + c)" begin lemma add_diff_cancel_right' [simp]: "(a + b) - b = a" using add_diff_cancel_left' [of b a] by (simp add: ac_simps) subclass cancel_semigroup_add proof fix a b c :: 'a assume "a + b = a + c" then have "a + b - a = a + c - a" by simp then show "b = c" by simp next fix a b c :: 'a assume "b + a = c + a" then have "b + a - a = c + a - a" by simp then show "b = c" by simp qed lemma add_diff_cancel_left [simp]: "(c + a) - (c + b) = a - b" unfolding diff_diff_add [symmetric] by simp lemma add_diff_cancel_right [simp]: "(a + c) - (b + c) = a - b" using add_diff_cancel_left [symmetric] by (simp add: ac_simps) lemma diff_right_commute: "a - c - b = a - b - c" by (simp add: diff_diff_add add.commute) end class cancel_comm_monoid_add = cancel_ab_semigroup_add + comm_monoid_add begin lemma diff_zero [simp]: "a - 0 = a" using add_diff_cancel_right' [of a 0] by simp lemma diff_cancel [simp]: "a - a = 0" proof - have "(a + 0) - (a + 0) = 0" by (simp only: add_diff_cancel_left diff_zero) then show ?thesis by simp qed lemma add_implies_diff: assumes "c + b = a" shows "c = a - b" proof - from assms have "(b + c) - (b + 0) = a - b" by (simp add: add.commute) then show "c = a - b" by simp qed lemma add_cancel_right_right [simp]: "a = a + b \ b = 0" (is "?P \ ?Q") proof assume ?Q then show ?P by simp next assume ?P then have "a - a = a + b - a" by simp then show ?Q by simp qed lemma add_cancel_right_left [simp]: "a = b + a \ b = 0" using add_cancel_right_right [of a b] by (simp add: ac_simps) lemma add_cancel_left_right [simp]: "a + b = a \ b = 0" by (auto dest: sym) lemma add_cancel_left_left [simp]: "b + a = a \ b = 0" by (auto dest: sym) end class comm_monoid_diff = cancel_comm_monoid_add + assumes zero_diff [simp]: "0 - a = 0" begin lemma diff_add_zero [simp]: "a - (a + b) = 0" proof - have "a - (a + b) = (a + 0) - (a + b)" by simp also have "\ = 0" by (simp only: add_diff_cancel_left zero_diff) finally show ?thesis . qed end subsection \Groups\ class group_add = minus + uminus + monoid_add + assumes left_minus: "- a + a = 0" assumes add_uminus_conv_diff [simp]: "a + (- b) = a - b" begin lemma diff_conv_add_uminus: "a - b = a + (- b)" by simp sublocale add: group plus 0 uminus by standard (simp_all add: left_minus) lemma minus_unique: "a + b = 0 \ - a = b" by (fact add.inverse_unique) lemma minus_zero: "- 0 = 0" by (fact add.inverse_neutral) lemma minus_minus: "- (- a) = a" by (fact add.inverse_inverse) lemma right_minus: "a + - a = 0" by (fact add.right_inverse) lemma diff_self [simp]: "a - a = 0" using right_minus [of a] by simp subclass cancel_semigroup_add by standard (simp_all add: add.left_cancel add.right_cancel) lemma minus_add_cancel [simp]: "- a + (a + b) = b" by (simp add: add.assoc [symmetric]) lemma add_minus_cancel [simp]: "a + (- a + b) = b" by (simp add: add.assoc [symmetric]) lemma diff_add_cancel [simp]: "a - b + b = a" by (simp only: diff_conv_add_uminus add.assoc) simp lemma add_diff_cancel [simp]: "a + b - b = a" by (simp only: diff_conv_add_uminus add.assoc) simp lemma minus_add: "- (a + b) = - b + - a" by (fact add.inverse_distrib_swap) lemma right_minus_eq [simp]: "a - b = 0 \ a = b" proof assume "a - b = 0" have "a = (a - b) + b" by (simp add: add.assoc) also have "\ = b" using \a - b = 0\ by simp finally show "a = b" . next assume "a = b" then show "a - b = 0" by simp qed lemma eq_iff_diff_eq_0: "a = b \ a - b = 0" by (fact right_minus_eq [symmetric]) lemma diff_0 [simp]: "0 - a = - a" by (simp only: diff_conv_add_uminus add_0_left) lemma diff_0_right [simp]: "a - 0 = a" by (simp only: diff_conv_add_uminus minus_zero add_0_right) lemma diff_minus_eq_add [simp]: "a - - b = a + b" by (simp only: diff_conv_add_uminus minus_minus) lemma neg_equal_iff_equal [simp]: "- a = - b \ a = b" proof assume "- a = - b" then have "- (- a) = - (- b)" by simp then show "a = b" by simp next assume "a = b" then show "- a = - b" by simp qed lemma neg_equal_0_iff_equal [simp]: "- a = 0 \ a = 0" by (subst neg_equal_iff_equal [symmetric]) simp lemma neg_0_equal_iff_equal [simp]: "0 = - a \ 0 = a" by (subst neg_equal_iff_equal [symmetric]) simp text \The next two equations can make the simplifier loop!\ lemma equation_minus_iff: "a = - b \ b = - a" proof - have "- (- a) = - b \ - a = b" by (rule neg_equal_iff_equal) then show ?thesis by (simp add: eq_commute) qed lemma minus_equation_iff: "- a = b \ - b = a" proof - have "- a = - (- b) \ a = -b" by (rule neg_equal_iff_equal) then show ?thesis by (simp add: eq_commute) qed lemma eq_neg_iff_add_eq_0: "a = - b \ a + b = 0" proof assume "a = - b" then show "a + b = 0" by simp next assume "a + b = 0" moreover have "a + (b + - b) = (a + b) + - b" by (simp only: add.assoc) ultimately show "a = - b" by simp qed lemma add_eq_0_iff2: "a + b = 0 \ a = - b" by (fact eq_neg_iff_add_eq_0 [symmetric]) lemma neg_eq_iff_add_eq_0: "- a = b \ a + b = 0" by (auto simp add: add_eq_0_iff2) lemma add_eq_0_iff: "a + b = 0 \ b = - a" by (auto simp add: neg_eq_iff_add_eq_0 [symmetric]) lemma minus_diff_eq [simp]: "- (a - b) = b - a" by (simp only: neg_eq_iff_add_eq_0 diff_conv_add_uminus add.assoc minus_add_cancel) simp lemma add_diff_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a + (b - c) = (a + b) - c" by (simp only: diff_conv_add_uminus add.assoc) lemma diff_add_eq_diff_diff_swap: "a - (b + c) = a - c - b" by (simp only: diff_conv_add_uminus add.assoc minus_add) lemma diff_eq_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a - b = c \ a = c + b" by auto lemma eq_diff_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a = c - b \ a + b = c" by auto lemma diff_diff_eq2 [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a - (b - c) = (a + c) - b" by (simp only: diff_conv_add_uminus add.assoc) simp lemma diff_eq_diff_eq: "a - b = c - d \ a = b \ c = d" by (simp only: eq_iff_diff_eq_0 [of a b] eq_iff_diff_eq_0 [of c d]) end class ab_group_add = minus + uminus + comm_monoid_add + assumes ab_left_minus: "- a + a = 0" assumes ab_diff_conv_add_uminus: "a - b = a + (- b)" begin subclass group_add by standard (simp_all add: ab_left_minus ab_diff_conv_add_uminus) subclass cancel_comm_monoid_add proof fix a b c :: 'a have "b + a - a = b" by simp then show "a + b - a = b" by (simp add: ac_simps) show "a - b - c = a - (b + c)" by (simp add: algebra_simps) qed lemma uminus_add_conv_diff [simp]: "- a + b = b - a" by (simp add: add.commute) lemma minus_add_distrib [simp]: "- (a + b) = - a + - b" by (simp add: algebra_simps) lemma diff_add_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "(a - b) + c = (a + c) - b" by (simp add: algebra_simps) lemma minus_diff_commute: "- b - a = - a - b" by (simp only: diff_conv_add_uminus add.commute) end subsection \(Partially) Ordered Groups\ text \ The theory of partially ordered groups is taken from the books: \<^item> \<^emph>\Lattice Theory\ by Garret Birkhoff, American Mathematical Society, 1979 \<^item> \<^emph>\Partially Ordered Algebraic Systems\, Pergamon Press, 1963 Most of the used notions can also be looked up in \<^item> \<^url>\http://www.mathworld.com\ by Eric Weisstein et. al. \<^item> \<^emph>\Algebra I\ by van der Waerden, Springer \ class ordered_ab_semigroup_add = order + ab_semigroup_add + assumes add_left_mono: "a \ b \ c + a \ c + b" begin lemma add_right_mono: "a \ b \ a + c \ b + c" by (simp add: add.commute [of _ c] add_left_mono) text \non-strict, in both arguments\ lemma add_mono: "a \ b \ c \ d \ a + c \ b + d" apply (erule add_right_mono [THEN order_trans]) apply (simp add: add.commute add_left_mono) done end text \Strict monotonicity in both arguments\ class strict_ordered_ab_semigroup_add = ordered_ab_semigroup_add + assumes add_strict_mono: "a < b \ c < d \ a + c < b + d" class ordered_cancel_ab_semigroup_add = ordered_ab_semigroup_add + cancel_ab_semigroup_add begin lemma add_strict_left_mono: "a < b \ c + a < c + b" by (auto simp add: less_le add_left_mono) lemma add_strict_right_mono: "a < b \ a + c < b + c" by (simp add: add.commute [of _ c] add_strict_left_mono) subclass strict_ordered_ab_semigroup_add apply standard apply (erule add_strict_right_mono [THEN less_trans]) apply (erule add_strict_left_mono) done lemma add_less_le_mono: "a < b \ c \ d \ a + c < b + d" apply (erule add_strict_right_mono [THEN less_le_trans]) apply (erule add_left_mono) done lemma add_le_less_mono: "a \ b \ c < d \ a + c < b + d" apply (erule add_right_mono [THEN le_less_trans]) apply (erule add_strict_left_mono) done end class ordered_ab_semigroup_add_imp_le = ordered_cancel_ab_semigroup_add + assumes add_le_imp_le_left: "c + a \ c + b \ a \ b" begin lemma add_less_imp_less_left: assumes less: "c + a < c + b" shows "a < b" proof - from less have le: "c + a \ c + b" by (simp add: order_le_less) have "a \ b" apply (insert le) apply (drule add_le_imp_le_left) apply (insert le) apply (drule add_le_imp_le_left) apply assumption done moreover have "a \ b" proof (rule ccontr) assume "\ ?thesis" then have "a = b" by simp then have "c + a = c + b" by simp with less show "False" by simp qed ultimately show "a < b" by (simp add: order_le_less) qed lemma add_less_imp_less_right: "a + c < b + c \ a < b" by (rule add_less_imp_less_left [of c]) (simp add: add.commute) lemma add_less_cancel_left [simp]: "c + a < c + b \ a < b" by (blast intro: add_less_imp_less_left add_strict_left_mono) lemma add_less_cancel_right [simp]: "a + c < b + c \ a < b" by (blast intro: add_less_imp_less_right add_strict_right_mono) lemma add_le_cancel_left [simp]: "c + a \ c + b \ a \ b" apply auto apply (drule add_le_imp_le_left) apply (simp_all add: add_left_mono) done lemma add_le_cancel_right [simp]: "a + c \ b + c \ a \ b" by (simp add: add.commute [of a c] add.commute [of b c]) lemma add_le_imp_le_right: "a + c \ b + c \ a \ b" by simp lemma max_add_distrib_left: "max x y + z = max (x + z) (y + z)" unfolding max_def by auto lemma min_add_distrib_left: "min x y + z = min (x + z) (y + z)" unfolding min_def by auto lemma max_add_distrib_right: "x + max y z = max (x + y) (x + z)" unfolding max_def by auto lemma min_add_distrib_right: "x + min y z = min (x + y) (x + z)" unfolding min_def by auto end subsection \Support for reasoning about signs\ class ordered_comm_monoid_add = comm_monoid_add + ordered_ab_semigroup_add begin lemma add_nonneg_nonneg [simp]: "0 \ a \ 0 \ b \ 0 \ a + b" using add_mono[of 0 a 0 b] by simp lemma add_nonpos_nonpos: "a \ 0 \ b \ 0 \ a + b \ 0" using add_mono[of a 0 b 0] by simp lemma add_nonneg_eq_0_iff: "0 \ x \ 0 \ y \ x + y = 0 \ x = 0 \ y = 0" using add_left_mono[of 0 y x] add_right_mono[of 0 x y] by auto lemma add_nonpos_eq_0_iff: "x \ 0 \ y \ 0 \ x + y = 0 \ x = 0 \ y = 0" using add_left_mono[of y 0 x] add_right_mono[of x 0 y] by auto lemma add_increasing: "0 \ a \ b \ c \ b \ a + c" using add_mono [of 0 a b c] by simp lemma add_increasing2: "0 \ c \ b \ a \ b \ a + c" by (simp add: add_increasing add.commute [of a]) lemma add_decreasing: "a \ 0 \ c \ b \ a + c \ b" using add_mono [of a 0 c b] by simp lemma add_decreasing2: "c \ 0 \ a \ b \ a + c \ b" using add_mono[of a b c 0] by simp lemma add_pos_nonneg: "0 < a \ 0 \ b \ 0 < a + b" using less_le_trans[of 0 a "a + b"] by (simp add: add_increasing2) lemma add_pos_pos: "0 < a \ 0 < b \ 0 < a + b" by (intro add_pos_nonneg less_imp_le) lemma add_nonneg_pos: "0 \ a \ 0 < b \ 0 < a + b" using add_pos_nonneg[of b a] by (simp add: add_commute) lemma add_neg_nonpos: "a < 0 \ b \ 0 \ a + b < 0" using le_less_trans[of "a + b" a 0] by (simp add: add_decreasing2) lemma add_neg_neg: "a < 0 \ b < 0 \ a + b < 0" by (intro add_neg_nonpos less_imp_le) lemma add_nonpos_neg: "a \ 0 \ b < 0 \ a + b < 0" using add_neg_nonpos[of b a] by (simp add: add_commute) lemmas add_sign_intros = add_pos_nonneg add_pos_pos add_nonneg_pos add_nonneg_nonneg add_neg_nonpos add_neg_neg add_nonpos_neg add_nonpos_nonpos end class strict_ordered_comm_monoid_add = comm_monoid_add + strict_ordered_ab_semigroup_add begin lemma pos_add_strict: "0 < a \ b < c \ b < a + c" using add_strict_mono [of 0 a b c] by simp end class ordered_cancel_comm_monoid_add = ordered_comm_monoid_add + cancel_ab_semigroup_add begin subclass ordered_cancel_ab_semigroup_add .. subclass strict_ordered_comm_monoid_add .. lemma add_strict_increasing: "0 < a \ b \ c \ b < a + c" using add_less_le_mono [of 0 a b c] by simp lemma add_strict_increasing2: "0 \ a \ b < c \ b < a + c" using add_le_less_mono [of 0 a b c] by simp end class ordered_ab_semigroup_monoid_add_imp_le = monoid_add + ordered_ab_semigroup_add_imp_le begin lemma add_less_same_cancel1 [simp]: "b + a < b \ a < 0" using add_less_cancel_left [of _ _ 0] by simp lemma add_less_same_cancel2 [simp]: "a + b < b \ a < 0" using add_less_cancel_right [of _ _ 0] by simp lemma less_add_same_cancel1 [simp]: "a < a + b \ 0 < b" using add_less_cancel_left [of _ 0] by simp lemma less_add_same_cancel2 [simp]: "a < b + a \ 0 < b" using add_less_cancel_right [of 0] by simp lemma add_le_same_cancel1 [simp]: "b + a \ b \ a \ 0" using add_le_cancel_left [of _ _ 0] by simp lemma add_le_same_cancel2 [simp]: "a + b \ b \ a \ 0" using add_le_cancel_right [of _ _ 0] by simp lemma le_add_same_cancel1 [simp]: "a \ a + b \ 0 \ b" using add_le_cancel_left [of _ 0] by simp lemma le_add_same_cancel2 [simp]: "a \ b + a \ 0 \ b" using add_le_cancel_right [of 0] by simp subclass cancel_comm_monoid_add by standard auto subclass ordered_cancel_comm_monoid_add by standard end class ordered_ab_group_add = ab_group_add + ordered_ab_semigroup_add begin subclass ordered_cancel_ab_semigroup_add .. subclass ordered_ab_semigroup_monoid_add_imp_le proof fix a b c :: 'a assume "c + a \ c + b" then have "(-c) + (c + a) \ (-c) + (c + b)" by (rule add_left_mono) then have "((-c) + c) + a \ ((-c) + c) + b" by (simp only: add.assoc) then show "a \ b" by simp qed lemma max_diff_distrib_left: "max x y - z = max (x - z) (y - z)" using max_add_distrib_left [of x y "- z"] by simp lemma min_diff_distrib_left: "min x y - z = min (x - z) (y - z)" using min_add_distrib_left [of x y "- z"] by simp lemma le_imp_neg_le: assumes "a \ b" shows "- b \ - a" proof - from assms have "- a + a \ - a + b" by (rule add_left_mono) then have "0 \ - a + b" by simp then have "0 + (- b) \ (- a + b) + (- b)" by (rule add_right_mono) then show ?thesis by (simp add: algebra_simps) qed lemma neg_le_iff_le [simp]: "- b \ - a \ a \ b" proof assume "- b \ - a" then have "- (- a) \ - (- b)" by (rule le_imp_neg_le) then show "a \ b" by simp next assume "a \ b" then show "- b \ - a" by (rule le_imp_neg_le) qed lemma neg_le_0_iff_le [simp]: "- a \ 0 \ 0 \ a" by (subst neg_le_iff_le [symmetric]) simp lemma neg_0_le_iff_le [simp]: "0 \ - a \ a \ 0" by (subst neg_le_iff_le [symmetric]) simp lemma neg_less_iff_less [simp]: "- b < - a \ a < b" by (auto simp add: less_le) lemma neg_less_0_iff_less [simp]: "- a < 0 \ 0 < a" by (subst neg_less_iff_less [symmetric]) simp lemma neg_0_less_iff_less [simp]: "0 < - a \ a < 0" by (subst neg_less_iff_less [symmetric]) simp text \The next several equations can make the simplifier loop!\ lemma less_minus_iff: "a < - b \ b < - a" proof - have "- (- a) < - b \ b < - a" by (rule neg_less_iff_less) then show ?thesis by simp qed lemma minus_less_iff: "- a < b \ - b < a" proof - have "- a < - (- b) \ - b < a" by (rule neg_less_iff_less) then show ?thesis by simp qed lemma le_minus_iff: "a \ - b \ b \ - a" proof - have mm: "- (- a) < - b \ - (- b) < -a" for a b :: 'a by (simp only: minus_less_iff) have "- (- a) \ - b \ b \ - a" apply (auto simp only: le_less) apply (drule mm) apply (simp_all) apply (drule mm[simplified], assumption) done then show ?thesis by simp qed lemma minus_le_iff: "- a \ b \ - b \ a" by (auto simp add: le_less minus_less_iff) lemma diff_less_0_iff_less [simp]: "a - b < 0 \ a < b" proof - have "a - b < 0 \ a + (- b) < b + (- b)" by simp also have "\ \ a < b" by (simp only: add_less_cancel_right) finally show ?thesis . qed lemmas less_iff_diff_less_0 = diff_less_0_iff_less [symmetric] lemma diff_less_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a - b < c \ a < c + b" apply (subst less_iff_diff_less_0 [of a]) apply (rule less_iff_diff_less_0 [of _ c, THEN ssubst]) apply (simp add: algebra_simps) done lemma less_diff_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a < c - b \ a + b < c" apply (subst less_iff_diff_less_0 [of "a + b"]) apply (subst less_iff_diff_less_0 [of a]) apply (simp add: algebra_simps) done lemma diff_gt_0_iff_gt [simp]: "a - b > 0 \ a > b" by (simp add: less_diff_eq) lemma diff_le_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a - b \ c \ a \ c + b" by (auto simp add: le_less diff_less_eq ) lemma le_diff_eq [algebra_simps, algebra_split_simps, field_simps, field_split_simps]: "a \ c - b \ a + b \ c" by (auto simp add: le_less less_diff_eq) lemma diff_le_0_iff_le [simp]: "a - b \ 0 \ a \ b" by (simp add: algebra_simps) lemmas le_iff_diff_le_0 = diff_le_0_iff_le [symmetric] lemma diff_ge_0_iff_ge [simp]: "a - b \ 0 \ a \ b" by (simp add: le_diff_eq) lemma diff_eq_diff_less: "a - b = c - d \ a < b \ c < d" by (auto simp only: less_iff_diff_less_0 [of a b] less_iff_diff_less_0 [of c d]) lemma diff_eq_diff_less_eq: "a - b = c - d \ a \ b \ c \ d" by (auto simp only: le_iff_diff_le_0 [of a b] le_iff_diff_le_0 [of c d]) lemma diff_mono: "a \ b \ d \ c \ a - c \ b - d" by (simp add: field_simps add_mono) lemma diff_left_mono: "b \ a \ c - a \ c - b" by (simp add: field_simps) lemma diff_right_mono: "a \ b \ a - c \ b - c" by (simp add: field_simps) lemma diff_strict_mono: "a < b \ d < c \ a - c < b - d" by (simp add: field_simps add_strict_mono) lemma diff_strict_left_mono: "b < a \ c - a < c - b" by (simp add: field_simps) lemma diff_strict_right_mono: "a < b \ a - c < b - c" by (simp add: field_simps) end locale group_cancel 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 sub1: "(A::'a::ab_group_add) \ k + a \ A - b \ k + (a - b)" by (simp only: add_diff_eq) lemma sub2: "(B::'a::ab_group_add) \ k + b \ a - B \ - k + (a - b)" by (simp only: minus_add diff_conv_add_uminus ac_simps) lemma neg1: "(A::'a::ab_group_add) \ k + a \ - A \ - k + - a" by (simp only: minus_add_distrib) lemma rule0: "(a::'a::comm_monoid_add) \ a + 0" by (simp only: add_0_right) end ML_file \Tools/group_cancel.ML\ simproc_setup group_cancel_add ("a + b::'a::ab_group_add") = \fn phi => fn ss => try Group_Cancel.cancel_add_conv\ simproc_setup group_cancel_diff ("a - b::'a::ab_group_add") = \fn phi => fn ss => try Group_Cancel.cancel_diff_conv\ simproc_setup group_cancel_eq ("a = (b::'a::ab_group_add)") = \fn phi => fn ss => try Group_Cancel.cancel_eq_conv\ simproc_setup group_cancel_le ("a \ (b::'a::ordered_ab_group_add)") = \fn phi => fn ss => try Group_Cancel.cancel_le_conv\ simproc_setup group_cancel_less ("a < (b::'a::ordered_ab_group_add)") = \fn phi => fn ss => try Group_Cancel.cancel_less_conv\ class linordered_ab_semigroup_add = linorder + ordered_ab_semigroup_add class linordered_cancel_ab_semigroup_add = linorder + ordered_cancel_ab_semigroup_add begin subclass linordered_ab_semigroup_add .. subclass ordered_ab_semigroup_add_imp_le proof fix a b c :: 'a assume le1: "c + a \ c + b" show "a \ b" proof (rule ccontr) assume *: "\ ?thesis" then have "b \ a" by (simp add: linorder_not_le) then have "c + b \ c + a" by (rule add_left_mono) with le1 have "a = b" apply - apply (drule antisym) apply simp_all done with * show False by (simp add: linorder_not_le [symmetric]) qed qed end class linordered_ab_group_add = linorder + ordered_ab_group_add begin subclass linordered_cancel_ab_semigroup_add .. lemma equal_neg_zero [simp]: "a = - a \ a = 0" proof assume "a = 0" then show "a = - a" by simp next assume A: "a = - a" show "a = 0" proof (cases "0 \ a") case True with A have "0 \ - a" by auto with le_minus_iff have "a \ 0" by simp with True show ?thesis by (auto intro: order_trans) next case False then have B: "a \ 0" by auto with A have "- a \ 0" by auto with B show ?thesis by (auto intro: order_trans) qed qed lemma neg_equal_zero [simp]: "- a = a \ a = 0" by (auto dest: sym) lemma neg_less_eq_nonneg [simp]: "- a \ a \ 0 \ a" proof assume *: "- a \ a" show "0 \ a" proof (rule classical) assume "\ ?thesis" then have "a < 0" by auto with * have "- a < 0" by (rule le_less_trans) then show ?thesis by auto qed next assume *: "0 \ a" then have "- a \ 0" by (simp add: minus_le_iff) from this * show "- a \ a" by (rule order_trans) qed lemma neg_less_pos [simp]: "- a < a \ 0 < a" by (auto simp add: less_le) lemma less_eq_neg_nonpos [simp]: "a \ - a \ a \ 0" using neg_less_eq_nonneg [of "- a"] by simp lemma less_neg_neg [simp]: "a < - a \ a < 0" using neg_less_pos [of "- a"] by simp lemma double_zero [simp]: "a + a = 0 \ a = 0" proof assume "a + a = 0" then have a: "- a = a" by (rule minus_unique) then show "a = 0" by (simp only: neg_equal_zero) next assume "a = 0" then show "a + a = 0" by simp qed lemma double_zero_sym [simp]: "0 = a + a \ a = 0" apply (rule iffI) apply (drule sym) apply simp_all done lemma zero_less_double_add_iff_zero_less_single_add [simp]: "0 < a + a \ 0 < a" proof assume "0 < a + a" then have "0 - a < a" by (simp only: diff_less_eq) then have "- a < a" by simp then show "0 < a" by simp next assume "0 < a" with this have "0 + 0 < a + a" by (rule add_strict_mono) then show "0 < a + a" by simp qed lemma zero_le_double_add_iff_zero_le_single_add [simp]: "0 \ a + a \ 0 \ a" by (auto simp add: le_less) lemma double_add_less_zero_iff_single_add_less_zero [simp]: "a + a < 0 \ a < 0" proof - have "\ a + a < 0 \ \ a < 0" by (simp add: not_less) then show ?thesis by simp qed lemma double_add_le_zero_iff_single_add_le_zero [simp]: "a + a \ 0 \ a \ 0" proof - have "\ a + a \ 0 \ \ a \ 0" by (simp add: not_le) then show ?thesis by simp qed lemma minus_max_eq_min: "- max x y = min (- x) (- y)" by (auto simp add: max_def min_def) lemma minus_min_eq_max: "- min x y = max (- x) (- y)" by (auto simp add: max_def min_def) end class abs = fixes abs :: "'a \ 'a" ("\_\") class sgn = fixes sgn :: "'a \ 'a" class ordered_ab_group_add_abs = ordered_ab_group_add + abs + assumes abs_ge_zero [simp]: "\a\ \ 0" and abs_ge_self: "a \ \a\" and abs_leI: "a \ b \ - a \ b \ \a\ \ b" and abs_minus_cancel [simp]: "\-a\ = \a\" and abs_triangle_ineq: "\a + b\ \ \a\ + \b\" begin lemma abs_minus_le_zero: "- \a\ \ 0" unfolding neg_le_0_iff_le by simp lemma abs_of_nonneg [simp]: assumes nonneg: "0 \ a" shows "\a\ = a" proof (rule antisym) show "a \ \a\" by (rule abs_ge_self) from nonneg le_imp_neg_le have "- a \ 0" by simp from this nonneg have "- a \ a" by (rule order_trans) then show "\a\ \ a" by (auto intro: abs_leI) qed lemma abs_idempotent [simp]: "\\a\\ = \a\" by (rule antisym) (auto intro!: abs_ge_self abs_leI order_trans [of "- \a\" 0 "\a\"]) lemma abs_eq_0 [simp]: "\a\ = 0 \ a = 0" proof - have "\a\ = 0 \ a = 0" proof (rule antisym) assume zero: "\a\ = 0" with abs_ge_self show "a \ 0" by auto from zero have "\-a\ = 0" by simp with abs_ge_self [of "- a"] have "- a \ 0" by auto with neg_le_0_iff_le show "0 \ a" by auto qed then show ?thesis by auto qed lemma abs_zero [simp]: "\0\ = 0" by simp lemma abs_0_eq [simp]: "0 = \a\ \ a = 0" proof - have "0 = \a\ \ \a\ = 0" by (simp only: eq_ac) then show ?thesis by simp qed lemma abs_le_zero_iff [simp]: "\a\ \ 0 \ a = 0" proof assume "\a\ \ 0" then have "\a\ = 0" by (rule antisym) simp then show "a = 0" by simp next assume "a = 0" then show "\a\ \ 0" by simp qed lemma abs_le_self_iff [simp]: "\a\ \ a \ 0 \ a" proof - have "0 \ \a\" using abs_ge_zero by blast then have "\a\ \ a \ 0 \ a" using order.trans by blast then show ?thesis using abs_of_nonneg eq_refl by blast qed lemma zero_less_abs_iff [simp]: "0 < \a\ \ a \ 0" by (simp add: less_le) lemma abs_not_less_zero [simp]: "\ \a\ < 0" proof - have "x \ y \ \ y < x" for x y by auto then show ?thesis by simp qed lemma abs_ge_minus_self: "- a \ \a\" proof - have "- a \ \-a\" by (rule abs_ge_self) then show ?thesis by simp qed lemma abs_minus_commute: "\a - b\ = \b - a\" proof - have "\a - b\ = \- (a - b)\" by (simp only: abs_minus_cancel) also have "\ = \b - a\" by simp finally show ?thesis . qed lemma abs_of_pos: "0 < a \ \a\ = a" by (rule abs_of_nonneg) (rule less_imp_le) lemma abs_of_nonpos [simp]: assumes "a \ 0" shows "\a\ = - a" proof - let ?b = "- a" have "- ?b \ 0 \ \- ?b\ = - (- ?b)" unfolding abs_minus_cancel [of ?b] unfolding neg_le_0_iff_le [of ?b] unfolding minus_minus by (erule abs_of_nonneg) then show ?thesis using assms by auto qed lemma abs_of_neg: "a < 0 \ \a\ = - a" by (rule abs_of_nonpos) (rule less_imp_le) lemma abs_le_D1: "\a\ \ b \ a \ b" using abs_ge_self by (blast intro: order_trans) lemma abs_le_D2: "\a\ \ b \ - a \ b" using abs_le_D1 [of "- a"] by simp lemma abs_le_iff: "\a\ \ b \ a \ b \ - a \ b" by (blast intro: abs_leI dest: abs_le_D1 abs_le_D2) lemma abs_triangle_ineq2: "\a\ - \b\ \ \a - b\" proof - have "\a\ = \b + (a - b)\" by (simp add: algebra_simps) then have "\a\ \ \b\ + \a - b\" by (simp add: abs_triangle_ineq) then show ?thesis by (simp add: algebra_simps) qed lemma abs_triangle_ineq2_sym: "\a\ - \b\ \ \b - a\" by (simp only: abs_minus_commute [of b] abs_triangle_ineq2) lemma abs_triangle_ineq3: "\\a\ - \b\\ \ \a - b\" by (simp add: abs_le_iff abs_triangle_ineq2 abs_triangle_ineq2_sym) lemma abs_triangle_ineq4: "\a - b\ \ \a\ + \b\" proof - have "\a - b\ = \a + - b\" by (simp add: algebra_simps) also have "\ \ \a\ + \- b\" by (rule abs_triangle_ineq) finally show ?thesis by simp qed lemma abs_diff_triangle_ineq: "\a + b - (c + d)\ \ \a - c\ + \b - d\" proof - have "\a + b - (c + d)\ = \(a - c) + (b - d)\" by (simp add: algebra_simps) also have "\ \ \a - c\ + \b - d\" by (rule abs_triangle_ineq) finally show ?thesis . qed lemma abs_add_abs [simp]: "\\a\ + \b\\ = \a\ + \b\" (is "?L = ?R") proof (rule antisym) show "?L \ ?R" by (rule abs_ge_self) have "?L \ \\a\\ + \\b\\" by (rule abs_triangle_ineq) also have "\ = ?R" by simp finally show "?L \ ?R" . qed end lemma dense_eq0_I: fixes x::"'a::{dense_linorder,ordered_ab_group_add_abs}" shows "(\e. 0 < e \ \x\ \ e) \ x = 0" apply (cases "\x\ = 0") apply simp apply (simp only: zero_less_abs_iff [symmetric]) apply (drule dense) apply (auto simp add: not_less [symmetric]) done hide_fact (open) ab_diff_conv_add_uminus add_0 mult_1 ab_left_minus lemmas add_0 = add_0_left (* FIXME duplicate *) lemmas mult_1 = mult_1_left (* FIXME duplicate *) lemmas ab_left_minus = left_minus (* FIXME duplicate *) lemmas diff_diff_eq = diff_diff_add (* FIXME duplicate *) subsection \Canonically ordered monoids\ text \Canonically ordered monoids are never groups.\ class canonically_ordered_monoid_add = comm_monoid_add + order + assumes le_iff_add: "a \ b \ (\c. b = a + c)" begin lemma zero_le[simp]: "0 \ x" by (auto simp: le_iff_add) lemma le_zero_eq[simp]: "n \ 0 \ n = 0" by (auto intro: antisym) lemma not_less_zero[simp]: "\ n < 0" by (auto simp: less_le) lemma zero_less_iff_neq_zero: "0 < n \ n \ 0" by (auto simp: less_le) text \This theorem is useful with \blast\\ lemma gr_zeroI: "(n = 0 \ False) \ 0 < n" by (rule zero_less_iff_neq_zero[THEN iffD2]) iprover lemma not_gr_zero[simp]: "\ 0 < n \ n = 0" by (simp add: zero_less_iff_neq_zero) subclass ordered_comm_monoid_add proof qed (auto simp: le_iff_add add_ac) lemma gr_implies_not_zero: "m < n \ n \ 0" by auto lemma add_eq_0_iff_both_eq_0[simp]: "x + y = 0 \ x = 0 \ y = 0" by (intro add_nonneg_eq_0_iff zero_le) lemma zero_eq_add_iff_both_eq_0[simp]: "0 = x + y \ x = 0 \ y = 0" using add_eq_0_iff_both_eq_0[of x y] unfolding eq_commute[of 0] . +lemma less_eqE: + assumes \a \ b\ + obtains c where \b = a + c\ + using assms by (auto simp add: le_iff_add) + +lemma lessE: + assumes \a < b\ + obtains c where \b = a + c\ and \c \ 0\ +proof - + from assms have \a \ b\ \a \ b\ + by simp_all + from \a \ b\ obtain c where \b = a + c\ + by (rule less_eqE) + moreover have \c \ 0\ using \a \ b\ \b = a + c\ + by auto + ultimately show ?thesis + by (rule that) +qed + lemmas zero_order = zero_le le_zero_eq not_less_zero zero_less_iff_neq_zero not_gr_zero \ \This should be attributed with \[iff]\, but then \blast\ fails in \Set\.\ end class ordered_cancel_comm_monoid_diff = canonically_ordered_monoid_add + comm_monoid_diff + ordered_ab_semigroup_add_imp_le begin context fixes a b :: 'a assumes le: "a \ b" begin lemma add_diff_inverse: "a + (b - a) = b" using le by (auto simp add: le_iff_add) lemma add_diff_assoc: "c + (b - a) = c + b - a" using le by (auto simp add: le_iff_add add.left_commute [of c]) lemma add_diff_assoc2: "b - a + c = b + c - a" using le by (auto simp add: le_iff_add add.assoc) lemma diff_add_assoc: "c + b - a = c + (b - a)" using le by (simp add: add.commute add_diff_assoc) lemma diff_add_assoc2: "b + c - a = b - a + c" using le by (simp add: add.commute add_diff_assoc) lemma diff_diff_right: "c - (b - a) = c + a - b" by (simp add: add_diff_inverse add_diff_cancel_left [of a c "b - a", symmetric] add.commute) lemma diff_add: "b - a + a = b" by (simp add: add.commute add_diff_inverse) lemma le_add_diff: "c \ b + c - a" by (auto simp add: add.commute diff_add_assoc2 le_iff_add) lemma le_imp_diff_is_add: "a \ b \ b - a = c \ b = c + a" by (auto simp add: add.commute add_diff_inverse) lemma le_diff_conv2: "c \ b - a \ c + a \ b" (is "?P \ ?Q") proof assume ?P then have "c + a \ b - a + a" by (rule add_right_mono) then show ?Q by (simp add: add_diff_inverse add.commute) next assume ?Q then have "a + c \ a + (b - a)" by (simp add: add_diff_inverse add.commute) then show ?P by simp qed end end subsection \Tools setup\ lemma add_mono_thms_linordered_semiring: fixes i j k :: "'a::ordered_ab_semigroup_add" shows "i \ j \ k \ l \ i + k \ j + l" and "i = j \ k \ l \ i + k \ j + l" and "i \ j \ k = l \ i + k \ j + l" and "i = j \ k = l \ i + k = j + l" by (rule add_mono, clarify+)+ lemma add_mono_thms_linordered_field: fixes i j k :: "'a::ordered_cancel_ab_semigroup_add" shows "i < j \ k = l \ i + k < j + l" and "i = j \ k < l \ i + k < j + l" and "i < j \ k \ l \ i + k < j + l" and "i \ j \ k < l \ i + k < j + l" and "i < j \ k < l \ i + k < j + l" by (auto intro: add_strict_right_mono add_strict_left_mono add_less_le_mono add_le_less_mono add_strict_mono) code_identifier code_module Groups \ (SML) Arith and (OCaml) Arith and (Haskell) Arith end diff --git a/src/HOL/Nat.thy b/src/HOL/Nat.thy --- a/src/HOL/Nat.thy +++ b/src/HOL/Nat.thy @@ -1,2529 +1,2533 @@ (* Title: HOL/Nat.thy Author: Tobias Nipkow Author: Lawrence C Paulson Author: Markus Wenzel *) section \Natural numbers\ theory Nat imports Inductive Typedef Fun 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 instantiation nat :: zero begin definition Zero_nat_def: "0 = Abs_Nat Zero_Rep" instance .. end definition Suc :: "nat \ nat" where "Suc n = Abs_Nat (Suc_Rep (Rep_Nat n))" lemma Suc_not_Zero: "Suc m \ 0" by (simp add: Zero_nat_def Suc_def Suc_RepI Zero_RepI Nat_Abs_Nat_inject Suc_Rep_not_Zero_Rep Nat_Rep_Nat) lemma Zero_not_Suc: "0 \ Suc m" by (rule not_sym) (rule Suc_not_Zero) 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" using assms apply (unfold Zero_nat_def Suc_def) apply (rule Rep_Nat_inverse [THEN subst]) \ \types force good instantiation\ apply (erule Nat_Rep_Nat [THEN Nat.induct]) apply (iprover elim: Nat_Abs_Nat_inverse [THEN subst]) done free_constructors case_nat for "0 :: nat" | Suc pred where "pred (0 :: nat) = (0 :: nat)" apply atomize_elim apply (rename_tac n, induct_tac n rule: nat_induct0, auto) apply (simp add: Suc_def Nat_Abs_Nat_inject Nat_Rep_Nat Suc_RepI Suc_Rep_inject' Rep_Nat_inject) apply (simp only: Suc_not_Zero) done \ \Avoid name clashes by prefixing the output of \old_rep_datatype\ with \old\.\ setup \Sign.mandatory_path "old"\ old_rep_datatype "0 :: nat" Suc apply (erule nat_induct0) apply assumption apply (rule nat.inject) apply (rule nat.distinct(1)) done 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] lemmas induct = old.nat.induct lemmas inducts = old.nat.inducts lemmas rec = old.nat.rec lemmas simps = nat.inject nat.distinct nat.case nat.rec setup \Sign.parent_path\ abbreviation rec_nat :: "'a \ (nat \ 'a \ 'a) \ nat \ 'a" where "rec_nat \ old.rec_nat" declare nat.sel[code del] hide_const (open) Nat.pred \ \hide everything related to the selector\ hide_fact nat.case_eq_if nat.collapse nat.expand nat.sel nat.exhaust_sel nat.split_sel nat.split_sel_asm lemma nat_exhaust [case_names 0 Suc, cases type: nat]: "(y = 0 \ P) \ (\nat. y = Suc nat \ P) \ P" \ \for backward compatibility -- names of variables differ\ by (rule old.nat.exhaust) 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 \<^theory> \<^type_name>\nat\); val recx = Logic.varify_types_global \<^term>\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 _ [\<^typ>\nat\] _ _ ctxt = ([], [0], [nat_basic_lfp_sugar], [], [], [], TrueI (*dummy*), [], false, ctxt) | 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 \<^term>\m < n\ and \<^term>\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 ?case by (rule assms(1)) next case (Suc n) show ?case proof (induct m) case 0 show ?case by (rule assms(2)) next case (Suc m) from \P m n\ show ?case by (rule assms(3)) qed qed subsection \Arithmetic operators\ instantiation nat :: comm_monoid_diff begin primrec plus_nat where add_0: "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 declare add_0 [code] 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 [simp]: "Suc n - 1 = 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 then show ?case by simp next case (Suc m) then show ?case by (induct n) auto qed lemma one_eq_mult_iff [simp]: "Suc 0 = m * n \ m = Suc 0 \ n = Suc 0" apply (rule trans) apply (rule_tac [2] mult_eq_1_iff) apply fastforce done lemma nat_mult_eq_1_iff [simp]: "m * n = 1 \ m = 1 \ n = 1" for m n :: nat unfolding One_nat_def by (rule mult_eq_1_iff) lemma nat_1_eq_mult_iff [simp]: "1 = m * n \ m = 1 \ n = 1" for m n :: nat unfolding One_nat_def by (rule one_eq_mult_iff) 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 then show "m = 0" by simp next case (Suc n) then show "m = Suc n" by (cases m) (simp_all add: eq_commute [of 0]) qed then show ?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 \<^typ>\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 then show ?case by (cases m) (simp_all add: less_eq_Suc_le) next case (Suc n) then show ?case by (cases m) (simp_all add: less_eq_Suc_le) qed show "n \ n" by (induct n) simp_all then show "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 ?case by simp next case (Suc n) then show ?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]) subsubsection \Introduction properties\ lemma lessI [iff]: "n < Suc n" by (simp add: less_Suc_eq_le) lemma zero_less_Suc [iff]: "0 < Suc n" by (simp add: less_Suc_eq_le) subsubsection \Elimination properties\ lemma less_not_refl: "\ n < n" for n :: nat by (rule order_less_irrefl) lemma less_not_refl2: "n < m \ m \ n" for m n :: nat by (rule not_sym) (rule less_imp_neq) lemma less_not_refl3: "s < t \ s \ t" for s t :: nat by (rule less_imp_neq) lemma less_irrefl_nat: "n < n \ R" for n :: nat by (rule notE, rule less_not_refl) lemma less_zeroE: "n < 0 \ R" for n :: nat by (rule notE) (rule not_less0) lemma less_Suc_eq: "m < Suc n \ m < n \ m = n" unfolding less_Suc_eq_le le_less .. lemma less_Suc0 [iff]: "(n < Suc 0) = (n = 0)" by (simp add: less_Suc_eq) 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 then have "(\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 apply (rule major [THEN lessE]) apply (rule eq) apply blast apply (rule less) apply blast done lemma Suc_lessE: assumes major: "Suc i < k" and minor: "\j. i < j \ k = Suc j \ P" shows P apply (rule major [THEN lessE]) apply (erule lessI [THEN minor]) apply (erule Suc_lessD [THEN minor]) apply assumption done 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 then show ?case by 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 \<^prop>\n = m \ n < m\.\ 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 < Suc n) = (Suc m \ n) = (m < n)\\ lemmas le_simps = less_imp_le_nat less_Suc_eq_le Suc_le_eq text \Equivalence of \m \ n\ and \m < n \ 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) lemmas not_less_simps = not_less_less_Suc_eq 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 then show ?case by auto next case (Suc n) then show ?case unfolding not_less_eq_eq [symmetric] using Suc_n_not_le_n assms order_trans strict_mono_less_eq by blast qed subsubsection \Monotonicity of Addition\ lemma Suc_pred [simp]: "n > 0 \ Suc (n - Suc 0) = n" by (simp add: diff_Suc split: nat.split) 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: "i < j \ k < l \ i + k < j + l" for i j k l :: nat apply (rule add_less_mono1 [THEN less_trans], assumption+) apply (induct j) apply simp_all done -text \Deleted \less_natE\; use \less_imp_Suc_add RS exE\\ lemma less_imp_Suc_add: "m < n \ \k. n = Suc (m + k)" proof (induct n) case 0 then show ?case by simp next case Suc then show ?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 < n\ + 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 < k\ proof (induct k) case 0 then show ?case by simp next case (Suc k) with \i < j\ show ?case by (cases k) (simp_all add: add_less_mono) qed text \Addition is the inverse of subtraction: if \<^term>\n \ m\ then \<^term>\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 :: 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 < n \ 0 < q \ q * m < q * 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) 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}\ instance nat :: ordered_cancel_comm_monoid_add .. instance nat :: ordered_cancel_comm_monoid_diff .. subsubsection \\<^term>\min\ and \<^term>\max\\ 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 (rule max_absorb2) simp lemma max_0R [simp]: "max n 0 = n" for n :: nat by (rule max_absorb1) simp 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) subsubsection \Additional theorems about \<^term>\(\)\\ text \Complete induction, aka course-of-values induction\ 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 ?case by auto next case (Suc m n) then have "n \ m \ n = Suc m" by (simp add: le_Suc_eq) then show ?case proof assume "n \ m" then show "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 then show "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: "P n \ \ P 0 \ (LEAST n. P n) = Suc (LEAST m. P (Suc m))" apply (cases n) apply auto apply (frule LeastI) apply (drule_tac P = "\x. P (Suc x)" in LeastI) apply (subgoal_tac " (LEAST x. P x) \ Suc (LEAST x. P (Suc x))") apply (erule_tac [2] Least_le) apply (cases "LEAST x. P x") apply auto apply (drule_tac P = "\x. P (Suc x)" in Least_le) apply (blast intro: order_antisym) done 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: "\ P 0 \ P n \ \k\n. (\i P i) \ P k" for P :: "nat \ bool" apply (cases n) apply blast apply (rule_tac x="LEAST k. P k" in exI) apply (blast intro: Least_le dest: not_less_Least intro: LeastI_ex) done lemma ex_least_nat_less: "\ P 0 \ P n \ \ki\k. \ P i) \ P (k + 1)" for P :: "nat \ bool" apply (cases n) apply blast apply (frule (1) ex_least_nat_le) apply (erule exE) apply (case_tac k) apply simp apply (rename_tac k1) apply (rule_tac x=k1 in exI) apply (auto simp add: less_eq_Suc_le) done 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 ?case by (simp add: step) next case (Suc k) have "0 + i < Suc k + i" by (rule add_less_mono1) simp then have "i < Suc (i + k)" by (simp add: add.commute) from trans[OF this lessI Suc step] show ?case by simp qed then show "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 \<^item> case ``0'': given \n = 0\ prove \P n\ \<^item> 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" apply (rule infinite_descent) using assms apply (case_tac "n > 0") apply auto done text \ Infinite descent using a mapping to \nat\: \P x\ is true for all \x \ D\ if there exists a \V \ D \ nat\ and \<^item> case ``0'': given \V x = 0\ prove \P x\ \<^item> ``smaller'': given \V x > 0\ and \\ P x\ prove there exists a \y \ D\ such that \V y < V 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 moreover have "\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) then obtain 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 then show ?case by auto qed ultimately show "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 moreover have "\x. V x = n \ P x" proof (induct n rule: infinite_descent, auto) show "\m < V x. \y. V y = m \ \ P y" if "\ P x" for x using assms and that by auto qed ultimately show "P x" by auto qed text \A (clumsy) way of lifting \<\ monotonicity to \\\ monotonicity\ lemma less_mono_imp_le_mono: fixes f :: "nat \ nat" and i j :: nat assumes "\i j::nat. i < j \ f i < f 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 < Suc (i + m)" by (rule le_less_trans, rule le_add1, rule lessI) lemma less_add_Suc2: "i < Suc (m + i)" by (rule le_less_trans, rule le_add2, rule lessI) lemma less_iff_Suc_add: "m < n \ (\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 < j \ i < j + m" for i j m :: nat by (rule less_le_trans, assumption, rule le_add1) lemma trans_less_add2: "i < j \ i < m + j" for i j m :: nat by (rule less_le_trans, assumption, rule le_add2) lemma add_lessD1: "i + j < k \ i < k" 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 < i" for i j :: nat apply (rule notI) apply (drule add_lessD1) apply (erule less_irrefl [THEN notE]) done lemma not_add_less2 [iff]: "\ j + i < i" for i j :: nat by (simp add: add.commute) 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 apply (simp add: add.commute) apply (erule add_leD1) done 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 < l \ m + l = k + n \ m < n" 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 < Suc m" apply (induct m n rule: diff_induct) apply (erule_tac [3] less_SucE) apply (simp_all add: less_Suc_eq) done 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 < k \ j - n < k" for j k n :: nat by (rule le_less_trans, rule diff_le_self) lemma diff_Suc_less [simp]: "0 < n \ n - Suc i < n" 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 (rule iffD2, rule diff_is_0_eq) lemma zero_less_diff [simp]: "0 < n - m \ m < n" for m n :: nat by (induct m n rule: diff_induct) simp_all lemma less_imp_add_positive: assumes "i < j" shows "\k::nat. 0 < k \ i + k = j" proof from assms show "0 < j - 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 < b \ P 0) \ (\d. a = b + d \ P d)" for a b :: nat \ \elimination of \-\ on \nat\\ by (cases "a < b") (auto simp add: not_less le_less dest!: add_eq_self_zero [OF sym]) lemma nat_diff_split_asm: "P (a - b) \ \ (a < b \ \ P 0 \ (\d. a = b + d \ \ P d))" for a b :: nat \ \elimination of \-\ on \nat\ in assumptions\ by (auto split: nat_diff_split) lemma Suc_pred': "0 < n \ 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 < n \ 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 < j \ 0 < k \ i * k < j * 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 < m * n \ 0 < m \ 0 < n" 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 < n * k \ 0 < k \ m < n" for k m n :: nat apply (safe intro!: mult_less_mono1) apply (cases k) apply auto apply (simp add: linorder_not_le [symmetric]) apply (blast intro: mult_le_mono1) done lemma mult_less_cancel1 [simp]: "k * m < k * n \ 0 < k \ m < n" for k m n :: nat by (simp add: mult.commute [of k]) lemma mult_le_cancel1 [simp]: "k * m \ k * n \ (0 < k \ 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 < k \ m \ n)" for k m n :: nat by (simp add: linorder_not_less [symmetric], auto) lemma Suc_mult_less_cancel1: "Suc k * m < Suc k * n \ m < n" 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: "m = m * n \ n = 1 \ m = 0" for m n :: nat apply (drule sym) apply (rule disjCI) apply (rule linorder_cases) defer apply assumption apply (drule mult_less_mono2) apply auto done 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 \<^typ>\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 ("(_\<^bsup>_\<^esup>)" [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.\ definition funpow :: "nat \ ('a \ 'a) \ 'a \ 'a" where funpow_code_def [code_abbrev]: "funpow = compow" lemma [code]: "funpow (Suc n) f = f \ funpow n f" "funpow 0 f = id" by (simp_all add: funpow_code_def) hide_const (open) funpow 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 arbitrary: A B) (auto simp del: funpow.simps(2) simp add: funpow_Suc_right 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]]]) 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::complete_lattice" 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\: \<^term>\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: \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 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 context linordered_nonzero_semiring begin lemma of_nat_0_le_iff [simp]: "0 \ of_nat n" by (induct n) simp_all lemma of_nat_less_0_iff [simp]: "\ of_nat m < 0" 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 < of_nat n \ m < n" 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 < n \ of_nat m < of_nat n" by simp lemma of_nat_less_imp_less: "of_nat m < of_nat n \ m < n" by simp text \Every \linordered_nonzero_semiring\ has characteristic zero.\ subclass semiring_char_0 by standard (auto intro!: injI simp add: 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 < of_nat n \ 0 < n" 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 \ \" apply (simp add: Nats_def) apply (rule range_eqI) apply (rule of_nat_0 [symmetric]) done lemma Nats_1 [simp]: "1 \ \" apply (simp add: Nats_def) apply (rule range_eqI) apply (rule of_nat_1 [symmetric]) done lemma Nats_add [simp]: "a \ \ \ b \ \ \ a + b \ \" apply (auto simp add: Nats_def) apply (rule range_eqI) apply (rule of_nat_add [symmetric]) done lemma Nats_mult [simp]: "a \ \ \ b \ \ \ a * b \ \" apply (auto simp add: Nats_def) apply (rule range_eqI) apply (rule of_nat_mult [symmetric]) done 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 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") = \fn phi => try o Nat_Arith.cancel_eq_conv\ simproc_setup natless_cancel_sums ("(l::nat) + m < n" | "(l::nat) < m + n" | "Suc m < n" | "m < Suc n") = \fn phi => 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") = \fn phi => 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") = \fn phi => try o Nat_Arith.cancel_diff_conv\ context order 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 < n'") case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono) 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 < n'") case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono) next case False with \n \ n'\ show ?thesis by auto qed lemma lift_Suc_mono_less: assumes mono: "\n. f n < f (Suc n)" and "n < n'" shows "f n < f n'" using \n < n'\ by (induct n n' rule: less_Suc_induct) (auto intro: mono) lemma lift_Suc_mono_less_iff: "(\n. f n < f (Suc n)) \ f n < f m \ n < m" 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 mono_nat_linear_lb: fixes f :: "nat \ nat" assumes "\m n. m < n \ f m < f 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 text \Subtraction laws, mostly by Clemens Ballarin\ lemma diff_less_mono: fixes a b c :: nat assumes "a < b" and "c \ a" shows "a - c < b - 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 < j - k \ i + k < j" 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 < i \ j < i + 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 < n \ 0 < m \ m - n < m" 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 < n - k \ m < n" 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 < n \ m < l \ l - n < l - 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 < m" 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 < n \ Suc 0 < m \ Suc 0 < m * n" using less_1_mult [of n m] by (simp add: ac_simps) lemma n_less_m_mult_n: "0 < n \ Suc 0 < m \ n < m * n" using mult_strict_right_mono [of 1 m n] by simp lemma n_less_n_mult_m: "0 < n \ Suc 0 < m \ n < 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 < j \ 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 < j" 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 < j\ 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 < j" moreover assume "P (Suc q)" ultimately show "P q" by (rule Suc.prems) qed with order_refl \n < j\ show "P n" by (rule Suc.prems) qed lemma strict_inc_induct [consumes 1, case_names base step]: assumes less: "i < j" and base: "\i. j = Suc i \ P i" and step: "\i. i < j \ P (Suc i) \ P i" shows "P i" using less proof (induct "j - i - 1" arbitrary: i) case (0 i) from \i < j\ 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 < j" by (simp add: not_le) ultimately have "P (Suc i)" by (rule Suc.hyps) with \i < j\ 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 < j \ 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 < Suc j" by simp moreover have "P j" using \i \ j\ \P i\ proof (rule Suc.hyps) fix q assume "i \ q" moreover assume "q < j" then have "q < Suc 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 < b-k" 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 GreatestI_nat: "\ P(k::nat); \y. P y \ y \ b \ \ P (Greatest P)" apply(drule (1) ex_has_greatest_nat) using GreatestI2_order by auto lemma Greatest_le_nat: "\ P(k::nat); \y. P y \ y \ b \ \ k \ (Greatest P)" apply(frule (1) ex_has_greatest_nat) using GreatestI2_order[where P=P and Q=\\x. k \ x\] by auto lemma GreatestI_ex_nat: "\ \k::nat. P k; \y. P y \ y \ b \ \ P (Greatest P)" apply (erule exE) apply (erule (1) GreatestI_nat) done subsection \Monotonicity of \funpow\\ lemma funpow_increasing: "m \ n \ mono f \ (f ^^ n) \ \ (f ^^ m) \" for f :: "'a::{lattice,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::{lattice,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::{lattice,order_bot} \ 'a" by (auto intro!: funpow_decreasing simp: mono_def) lemma antimono_funpow: "mono Q \ antimono (\i. (Q ^^ i) \)" for Q :: "'a::{lattice,order_top} \ 'a" by (auto intro!: funpow_increasing simp: antimono_def) subsection \The divides relation on \<^typ>\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: "k dvd m - n \ k dvd n \ n \ m \ k dvd m" for k m n :: nat apply (erule linorder_not_less [THEN iffD2, THEN add_diff_inverse, THEN subst]) apply (blast intro: dvd_add) done 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 < k" 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 < k\ have "n = m * q" by (auto simp add: mult_left_cancel) then show ?thesis .. qed lemma dvd_mult_cancel1: "0 < m \ m * n dvd m \ n = 1" for m n :: nat apply auto apply (subgoal_tac "m * n dvd m * 1") apply (drule dvd_mult_cancel) apply auto done lemma dvd_mult_cancel2: "0 < m \ 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 < n \ k \ n" for k n :: nat by (auto elim!: dvdE) (auto simp add: gr0_conv_Suc) lemma nat_dvd_not_less: "0 < m \ m < n \ \ 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 \ m dvd n" for m n :: nat by (cases "n < m") (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 nat_add_left_cancel: "k + m = k + n \ m = n" for k m n :: nat by (fact add_left_cancel) lemma nat_add_right_cancel: "m + k = n + k \ m = n" for k m n :: nat by (fact add_right_cancel) 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') lemma le_add_diff: "k \ n \ m \ n + m - k" for k m n :: nat by (fact le_add_diff) (* FIXME delete *) lemma le_diff_conv2: "k \ j \ (i \ j - k) = (i + k \ j)" for i j k :: nat by (fact le_diff_conv2) (* FIXME delete *) 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) lemmas nat_distrib = add_mult_distrib distrib_left diff_mult_distrib diff_mult_distrib2 subsection \Size of a datatype value\ 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 subsection \Code module namespace\ code_identifier code_module Nat \ (SML) Arith and (OCaml) Arith and (Haskell) Arith hide_const (open) of_nat_aux end