# HG changeset patch # User wenzelm # Date 1464007394 -7200 # Node ID ccbdce905fca72e247792318c533daf650a3fd83 # Parent 87a4283537e408e58d80f30b2ca324e4ba90e54b misc tuning and modernization; diff -r 87a4283537e4 -r ccbdce905fca src/HOL/Nat.thy --- a/src/HOL/Nat.thy Mon May 23 12:48:24 2016 +0200 +++ b/src/HOL/Nat.thy Mon May 23 14:43:14 2016 +0200 @@ -21,10 +21,10 @@ typedecl ind -axiomatization Zero_Rep :: ind and Suc_Rep :: "ind => ind" where - \ \the axiom of infinity in 2 parts\ - Suc_Rep_inject: "Suc_Rep x = Suc_Rep y ==> x = y" and - Suc_Rep_not_Zero_Rep: "Suc_Rep x \ Zero_Rep" +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\ @@ -120,8 +120,8 @@ setup \Sign.parent_path\ -abbreviation rec_nat :: "'a \ (nat \ 'a \ 'a) \ nat \ 'a" where - "rec_nat \ old.rec_nat" +abbreviation rec_nat :: "'a \ (nat \ 'a \ 'a) \ nat \ 'a" + where "rec_nat \ old.rec_nat" declare nat.sel[code del] @@ -199,8 +199,12 @@ text \A special form of induction for reasoning about @{term "m < n"} and @{term "m - n"}\ -lemma diff_induct: "(!!x. P x 0) ==> (!!y. P 0 (Suc y)) ==> - (!!x y. P x y ==> P (Suc x) (Suc y)) ==> P 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" + using assms apply (rule_tac x = m in spec) apply (induct n) prefer 2 @@ -215,10 +219,10 @@ 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::nat)" + 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)" @@ -231,17 +235,18 @@ 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)" +| 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::nat)" +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 +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 @@ -265,25 +270,24 @@ mult_0: "0 * n = (0::nat)" | mult_Suc: "Suc m * n = n + (m * n)" -lemma mult_0_right [simp]: "(m::nat) * 0 = 0" +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)::nat)" +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 n m q :: nat +instance +proof + fix k n m q :: nat show "0 \ (1::nat)" unfolding One_nat_def by simp show "1 * n = n" unfolding One_nat_def 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) -next - fix k m n :: nat - show "k * ((m::nat) - n) = (k * m) - (k * n)" + show "k * (m - n) = (k * m) - (k * n)" by (induct m n rule: diff_induct) simp_all qed @@ -294,29 +298,23 @@ text \Reasoning about \m + 0 = 0\, etc.\ -lemma add_is_0 [iff]: - fixes m n :: nat - shows "(m + n = 0) = (m = 0 & n = 0)" +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)" +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)" +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: - fixes m n :: nat - shows "m + n = m \ n = 0" +lemma add_eq_self_zero: "m + n = m \ n = 0" for m n :: nat by (induct m) simp_all -lemma inj_on_add_nat[simp]: "inj_on (%n::nat. n+k) N" +lemma inj_on_add_nat[simp]: "inj_on (\n. n + k) N" for k :: nat apply (induct k) apply simp - apply(drule comp_inj_on[OF _ inj_Suc]) - apply (simp add:o_def) + apply (drule comp_inj_on[OF _ inj_Suc]) + apply (simp add: o_def) done lemma Suc_eq_plus1: "Suc n = n + 1" @@ -336,43 +334,45 @@ subsubsection \Multiplication\ -lemma mult_is_0 [simp]: "((m::nat) * n = 0) = (m=0 | n=0)" +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)" +lemma mult_eq_1_iff [simp]: "m * n = Suc 0 \ m = Suc 0 \ n = Suc 0" apply (induct m) apply simp apply (induct n) apply auto done -lemma one_eq_mult_iff [simp]: "(Suc 0 = m * n) = (m = Suc 0 & n = Suc 0)" +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, fastforce) done -lemma nat_mult_eq_1_iff [simp]: "m * n = (1::nat) \ m = 1 \ n = 1" +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::nat) = m * n \ m = 1 \ n = 1" +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::nat)))" +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 + 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"]) + 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::nat)))" +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)" +lemma Suc_mult_cancel1: "Suc k * m = Suc k * n \ m = n" by (subst mult_cancel1) simp @@ -388,8 +388,12 @@ | "Suc m \ n \ (case n of 0 \ False | Suc n \ m \ n)" declare less_eq_nat.simps [simp del] -lemma le0 [iff]: "0 \ (n::nat)" by (simp add: less_eq_nat.simps) -lemma [code]: "(0::nat) \ n \ True" by simp + +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" @@ -400,13 +404,13 @@ lemma Suc_le_eq [code]: "Suc m \ n \ m < n" unfolding less_eq_Suc_le .. -lemma le_0_eq [iff]: "(n::nat) \ 0 \ n = 0" +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::nat)" +lemma not_less0 [iff]: "\ n < 0" for n :: nat by (simp add: less_eq_Suc_le) -lemma less_nat_zero_code [code]: "n < (0::nat) \ False" +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" @@ -419,8 +423,7 @@ 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) + 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) @@ -433,33 +436,32 @@ instance proof - fix n m :: nat + 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) + 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) + case (Suc n) + then show ?case by (cases m) (simp_all add: less_eq_Suc_le) qed -next - fix n :: nat show "n \ n" by (induct n) simp_all -next - fix n m :: nat assume "n \ m" and "m \ n" - then show "n = m" - by (induct n arbitrary: m) + 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) -next - fix n m q :: nat assume "n \ m" and "m \ q" - then show "n \ q" + show "n \ q" if "n \ m" and "m \ q" + using that proof (induct n arbitrary: m q) - case 0 show ?case by simp + case 0 + show ?case by simp next - case (Suc n) then show ?case + 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 -next - fix n m :: nat show "n \ m \ m \ n" + show "n \ m \ m \ n" by (induct n arbitrary: m) (simp_all add: less_eq_nat.simps(2) split: nat.splits) qed @@ -469,11 +471,9 @@ instantiation nat :: order_bot begin -definition bot_nat :: nat where - "bot_nat = 0" - -instance proof -qed (simp add: bot_nat_def) +definition bot_nat :: nat where "bot_nat = 0" + +instance by standard (simp add: bot_nat_def) end @@ -492,94 +492,104 @@ subsubsection \Elimination properties\ -lemma less_not_refl: "~ n < (n::nat)" +lemma less_not_refl: "\ n < n" for n :: nat by (rule order_less_irrefl) -lemma less_not_refl2: "n < m ==> m \ (n::nat)" +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::nat) < t ==> s \ t" +lemma less_not_refl3: "s < t \ s \ t" for s t :: nat by (rule less_imp_neq) -lemma less_irrefl_nat: "(n::nat) < n ==> R" +lemma less_irrefl_nat: "n < n \ R" for n :: nat by (rule notE, rule less_not_refl) -lemma less_zeroE: "(n::nat) < 0 ==> R" +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)" +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::nat)) = (n = 0)" +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" +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::nat) \ n) = (m < n | n < m)" +lemma nat_neq_iff: "m \ n \ m < n \ n < m" for m n :: nat by (rule linorder_neq_iff) -lemma nat_less_cases: assumes major: "(m::nat) < n ==> P n m" - and eqCase: "m = n ==> P n m" and lessCase: "n P n m" +lemma nat_less_cases: + fixes m n :: nat + assumes major: "m < n \ P n m" + and eq: "m = n \ P n m" + and less: "n < m \ P n m" shows "P n m" apply (rule less_linear [THEN disjE]) apply (erule_tac [2] disjE) - apply (erule lessCase) - apply (erule sym [THEN eqCase]) + apply (erule less) + apply (erule sym [THEN eq]) apply (erule major) done subsubsection \Inductive (?) properties\ -lemma Suc_lessI: "m < n ==> Suc m \ n ==> Suc m < n" +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 p1: "k = Suc i ==> P" and p2: "!!j. i < j ==> k = Suc j ==> P" + 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 (clarsimp simp add: less_le) - with p1 p2 show P by auto + 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 +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, blast) apply (rule less, blast) done -lemma Suc_lessE: assumes major: "Suc i < k" - and minor: "!!j. i < j ==> k = Suc j ==> P" shows P +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], assumption) done -lemma Suc_less_SucD: "Suc m < Suc n ==> m < n" +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" + assumes le: "i < j" + shows "j < k \ Suc i < k" apply (induct k, simp_all) - apply (insert le) + using le apply (simp add: less_Suc_eq) apply (blast dest: Suc_lessD) done -text \Can be used with \less_Suc_eq\ to get @{term "n = m | n < m"}\ +text \Can be used with \less_Suc_eq\ to get @{prop "n = m \ n < m"}\ lemma not_less_eq: "\ m < n \ n < Suc m" unfolding not_less less_Suc_eq_le .. @@ -588,138 +598,138 @@ text \Properties of "less than or equal"\ -lemma le_imp_less_Suc: "m \ n ==> m < Suc n" +lemma le_imp_less_Suc: "m \ n \ m < Suc n" unfolding less_Suc_eq_le . -lemma Suc_n_not_le_n: "~ Suc n \ n" +lemma Suc_n_not_le_n: "\ Suc n \ n" unfolding 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" +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" +lemma Suc_leI: "m < n \ Suc(m) \ n" unfolding Suc_le_eq . text \Stronger version of \Suc_leD\\ -lemma Suc_le_lessD: "Suc m \ n ==> m < n" +lemma Suc_le_lessD: "Suc m \ n \ m < n" unfolding Suc_le_eq . -lemma less_imp_le_nat: "m < n ==> m \ (n::nat)" +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 @{term "m \ n"} and @{term "m < n | m = n"}\ - -lemma less_or_eq_imp_le: "m < n | m = n ==> m \ (n::nat)" +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::nat)) = (m < n | m=n)" +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::nat) = n ==> m \ n" +lemma eq_imp_le: "m = n \ m \ n" for m n :: nat by auto -lemma le_refl: "n \ (n::nat)" +lemma le_refl: "n \ n" for n :: nat by simp -lemma le_trans: "[| i \ j; j \ k |] ==> i \ (k::nat)" +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::nat)" +lemma le_antisym: "m \ n \ n \ m \ m = n" for m n :: nat by (rule antisym) -lemma nat_less_le: "((m::nat) < n) = (m \ n & m \ n)" +lemma nat_less_le: "m < n \ m \ n \ m \ n" for m n :: nat by (rule less_le) -lemma le_neq_implies_less: "(m::nat) \ n ==> m \ n ==> m < n" +lemma le_neq_implies_less: "m \ n \ m \ n \ m < n" for m n :: nat unfolding less_le .. -lemma nat_le_linear: "(m::nat) \ n | n \ m" +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)" +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)" +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: fixes n :: nat shows "m n \ 0" -by (cases n) simp_all - -lemma neq0_conv[iff]: fixes n :: nat shows "(n \ 0) = (0 < n)" -by (cases n) simp_all +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::nat) = 0 ==> False) ==> 0 < n" -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]: "!!n::nat. (~ (0 < n)) = (n = 0)" -using neq0_conv by blast - -lemma Suc_le_D: "(Suc n \ m') ==> (? m. m' = Suc m)" -by (induct m') simp_all +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 less_Suc_eq_0_disj: "m < Suc n \ m = 0 \ (\j. m = Suc j \ j < n)" + by (cases m) simp_all 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::nat))" -by (induct k) simp_all - -lemma nat_add_left_cancel_less [simp]: "(k + m < k + n) = (m<(n::nat))" -by (induct k) simp_all - -lemma add_gr_0 [iff]: "!!m::nat. (m + n > 0) = (m>0 | n>0)" -by(auto dest:gr0_implies_Suc) +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::nat)" -by (induct k) simp_all +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::nat)" +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, 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))" +lemma less_imp_Suc_add: "m < n \ \k. n = Suc (m + k)" apply (induct n) apply (simp_all add: order_le_less) apply (blast elim!: less_SucE intro!: Nat.add_0_right [symmetric] add_Suc_right [symmetric]) done -lemma le_Suc_ex: "(k::nat) \ l \ (\n. l = k + n)" +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) text \strict, in 1st argument; proof is by induction on \k > 0\\ @@ -727,173 +737,162 @@ 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 + using \0 < k\ +proof (induct k) + case 0 + then show ?case by simp next - case (Suc k) with \i < j\ show ?case + 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::nat)" -by (induct m n rule: diff_induct) simp_all - -lemma nat_le_iff_add: "(m::nat) \ n = (\k. n = m + k)" -using nat_add_left_cancel_le[of m 0] by (auto dest: le_Suc_ex) +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 :: nat. m \ n \ q + m \ q + n" by simp - show "\m n q :: nat. m < n \ 0 < q \ q * m < q * n" by (simp add: mult_less_mono2) - show "\m n :: nat. m \ 0 \ n \ 0 \ m * n \ 0" by simp - show "\m n :: nat. n \ m ==> (m - n) + n = (m::nat)" + 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 - proof qed (rule nat_le_iff_add) + 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 - proof qed - -instance nat :: ordered_cancel_comm_monoid_diff - proof qed +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::nat)" -by (rule min_absorb1) simp - -lemma min_0R [simp]: "min n 0 = (0::nat)" -by (rule min_absorb2) simp + 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::nat)" -by (rule max_absorb2) simp - -lemma max_0R [simp]: "max n 0 = (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: - fixes m n q :: nat - shows "min m n * q = min (m * q) (n * q)" - 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: - fixes m n q :: nat - shows "m * min n q = min (m * n) (m * q)" - 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: - fixes m n q :: nat - shows "max m n + q = max (m + q) (n + q)" + 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: - fixes m n q :: nat - shows "m + max n q = max (m + n) (m + q)" +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: - fixes m n q :: nat - shows "max m n * q = max (m * q) (n * q)" - 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: - fixes m n q :: nat - shows "m * max n q = max (m * n) (m * q)" - by (simp add: max_def not_le) (auto dest: mult_left_le_imp_le mult_left_less_imp_less le_less_trans) +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 "op \"}\ text \Complete induction, aka course-of-values induction\ -instance nat :: wellorder proof +instance nat :: wellorder +proof fix P and n :: nat - assume step: "\n::nat. (\m. m < n \ P m) \ P n" + 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 - thus ?case using 0 by auto + then show ?case using 0 by auto next case (Suc m n) then have "n \ m \ n = Suc m" by (simp add: le_Suc_eq) - thus ?case + then show ?case proof - assume "n \ m" thus "P n" by (rule Suc(1)) + 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) + 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::nat) \ Least P = 0" -by (rule Least_equality[OF _ le0]) - -lemma Least_Suc: - "[| P n; ~ P 0 |] ==> (LEAST n. P n) = Suc (LEAST m. P(Suc m))" +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, auto) apply (frule LeastI) - apply (drule_tac P = "%x. P (Suc x) " in 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", auto) - apply (drule_tac P = "%x. P (Suc x) " in Least_le) + 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)" +lemma Least_Suc2: "P n \ Q m \ \ P 0 \ \k. P (Suc k) = Q k \ Least P = Suc (Least Q)" apply (erule (1) Least_Suc [THEN ssubst]) apply simp done -lemma ex_least_nat_le: "\P(0) \ P(n::nat) \ \k\n. (\iP i) & P(k)" +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 (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::nat) \ \ki\k. \P i) & P(k+1)" +lemma ex_least_nat_less: "\ P 0 \ P n \ \ki\k. \ P i) \ P (k + 1)" for P :: "nat \ bool" unfolding One_nat_def apply (cases n) apply blast @@ -907,14 +906,16 @@ done lemma nat_less_induct: - assumes "!!n. \m::nat. m < n --> P m ==> P n" shows "P n" + 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 \ nat" 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) + by (induct m \ "f a" arbitrary: a rule: less_induct) (auto intro: step) text \old style induction rules:\ lemma measure_induct: @@ -923,18 +924,19 @@ by (rule measure_induct_rule [of f P a]) iprover lemma full_nat_induct: - assumes step: "(!!n. (ALL m. Suc m <= n --> P m) ==> P n)" + 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 estabilishing binary relations\ +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" + 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) + 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 @@ -942,11 +944,11 @@ next case (Suc k) have "0 + i < Suc k + i" by (rule add_less_mono1) simp - hence "i < Suc (i + k)" by (simp add: add.commute) + then have "i < Suc (i + k)" by (simp add: add.commute) from trans[OF this lessI Suc step] show ?case by simp qed - thus "P i j" by (simp add: j) + then show "P i j" by (simp add: j) qed text \The method of infinite descent, frequently used in number theory. @@ -959,13 +961,18 @@ \end{itemize}\ text\A compact version without explicit base case:\ -lemma infinite_descent: - "\ !!n::nat. \ P n \ \m P m \ \ P n" -by (induct n rule: less_induct) auto +lemma infinite_descent: "(\n. \ P n \ \m P m) \ P n" for P :: "nat \ bool" + by (induct n rule: less_induct) auto lemma infinite_descent0[case_names 0 smaller]: - "\ P 0; !!n. n>0 \ \ P n \ (\m::nat. m < n \ \P m) \ \ P n" -by (rule infinite_descent) (case_tac "n>0", auto) + 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 $\mathbb{N}$: @@ -977,20 +984,21 @@ NB: the proof also shows how to use the previous lemma.\ corollary infinite_descent0_measure [case_names 0 smaller]: - assumes A0: "!!x. V x = (0::nat) \ P x" - and A1: "!!x. V x > 0 \ \P x \ (\y. V y < V x \ \P y)" + 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 \ "i.e. $V(x) = 0$" - with A0 show "P x" by auto - next \ "now $n>0$ and $P(x)$ does not hold for some $x$ with $V(x)=n$" + case 0 + with 1 show "P x" by auto + next case (smaller n) - then obtain x where vxn: "V x = n " and "V x > 0 \ \ P x" by auto - with A1 obtain y where "V y < V x \ \ P y" by auto - with vxn obtain m where "m = V y \ m \ P y" by auto + 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 \ P y" by auto then show ?case by auto qed ultimately show "P x" by auto @@ -998,96 +1006,97 @@ text\Again, without explicit base case:\ lemma infinite_descent_measure: -assumes "!!x. \ P x \ \y. (V::'a\nat) y < V x \ \ P y" shows "P x" + 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" + moreover have "\x. V x = n \ P x" proof (induct n rule: infinite_descent, auto) - fix x assume "\ P x" + fix x + assume "\ P x" with assms show "\m < V x. \y. V y = m \ \ P y" by auto qed ultimately show "P x" by auto qed -text \A [clumsy] way of lifting \<\ - monotonicity to \\\ monotonicity\ +text \A [clumsy] way of lifting \<\ monotonicity to \\\ monotonicity\ lemma less_mono_imp_le_mono: - "\ !!i j::nat. i < j \ f i < f j; i \ j \ \ f i \ ((f j)::nat)" -by (simp add: order_le_less) (blast) + 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::nat)" -by (rule add_right_mono) +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::nat)" -by (rule add_mono) - -lemma le_add2: "n \ ((m + n)::nat)" +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)::nat)" +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) + 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::nat) \ j ==> i \ j + m" -by (rule le_trans, assumption, rule le_add1) - -lemma trans_le_add2: "(i::nat) \ j ==> i \ m + j" -by (rule le_trans, assumption, rule le_add2) - -lemma trans_less_add1: "(i::nat) < j ==> i < j + m" -by (rule less_le_trans, assumption, rule le_add1) - -lemma trans_less_add2: "(i::nat) < j ==> i < m + j" -by (rule less_le_trans, assumption, rule le_add2) - -lemma add_lessD1: "i + j < (k::nat) ==> i < k" -apply (rule le_less_trans [of _ "i+j"]) -apply (simp_all add: le_add1) -done - -lemma not_add_less1 [iff]: "~ (i + j < (i::nat))" -apply (rule notI) -apply (drule add_lessD1) -apply (erule less_irrefl [THEN notE]) -done - -lemma not_add_less2 [iff]: "~ (j + i < (i::nat))" -by (simp add: add.commute) - -lemma add_leD1: "m + k \ n ==> m \ (n::nat)" -apply (rule order_trans [of _ "m+k"]) -apply (simp_all add: le_add1) -done - -lemma add_leD2: "m + k \ n ==> k \ (n::nat)" -apply (simp add: add.commute) -apply (erule add_leD1) -done - -lemma add_leE: "(m::nat) + k \ n ==> (m \ n ==> k \ n ==> R) ==> R" -by (blast dest: add_leD1 add_leD2) - -text \needs \!!k\ for \ac_simps\ to work\ -lemma less_add_eq_less: "!!k::nat. k < l ==> m + l = k + n ==> m < n" -by (force simp del: add_Suc_right - simp add: less_iff_Suc_add add_Suc_right [symmetric] ac_simps) + 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::nat. k < l \ m + l = k + n \ m < n" + 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 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) @@ -1095,80 +1104,72 @@ apply (simp_all add: less_Suc_eq) done -lemma diff_le_self [simp]: "m - n \ (m::nat)" -by (induct m n rule: diff_induct) (simp_all add: le_SucI) - -lemma less_imp_diff_less: "(j::nat) < k ==> j - n < k" -by (rule le_less_trans, rule diff_le_self) - -lemma diff_Suc_less [simp]: "0 n - Suc i < n" -by (cases n) (auto simp add: le_simps) - -lemma diff_add_assoc: "k \ (j::nat) ==> (i + j) - k = i + (j - k)" -by (induct j k rule: diff_induct) simp_all - -lemma add_diff_assoc [simp]: - fixes i j k :: nat - shows "k \ j \ i + (j - k) = i + j - k" +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 (induct j k rule: diff_induct) simp_all + +lemma add_diff_assoc [simp]: "k \ j \ i + (j - k) = i + j - k" for i j k :: nat by (fact diff_add_assoc [symmetric]) -lemma diff_add_assoc2: "k \ (j::nat) ==> (j + i) - k = (j - k) + i" +lemma diff_add_assoc2: "k \ j \ (j + i) - k = (j - k) + i" for i j k :: nat by (simp add: ac_simps) -lemma add_diff_assoc2 [simp]: - fixes i j k :: nat - shows "k \ j \ j - k + i = j + i - k" +lemma add_diff_assoc2 [simp]: "k \ j \ j - k + i = j + i - k" for i j k :: nat by (fact diff_add_assoc2 [symmetric]) -lemma le_imp_diff_is_add: "i \ (j::nat) ==> (j - i = k) = (j = k + i)" -by auto - -lemma diff_is_0_eq [simp]: "((m::nat) - n = 0) = (m \ n)" -by (induct m n rule: diff_induct) simp_all - -lemma diff_is_0_eq' [simp]: "m \ n ==> (m::nat) - n = 0" -by (rule iffD2, rule diff_is_0_eq) - -lemma zero_less_diff [simp]: "(0 < n - (m::nat)) = (m < n)" -by (induct m n rule: diff_induct) simp_all +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" + shows "\k::nat. 0 < k \ i + k = j" proof - from assms show "0 < j - i & i + (j - i) = j" + 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: - fixes n m :: nat - shows "n - m + m = max n m" +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: - fixes a b :: nat - shows "P (a - b) \ (a < b \ P 0) \ (\d. a = b + d \ P d)" +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: - fixes a b :: nat - shows "P (a - b) \ \ (a < b \ \ P 0 \ (\d. a = b + d \ \ P d))" +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)" +lemma Suc_pred': "0 < n \ n = Suc(n - 1)" by simp -lemma add_eq_if: "(m::nat) + n = (if m=0 then n else Suc ((m - 1) + n))" +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::nat) * n = (if m=0 then 0 else n + ((m - 1) * n))" +lemma mult_eq_if: "m * n = (if m = 0 then 0 else n + ((m - 1) * n))" for m n :: nat unfolding One_nat_def by (cases m) simp_all -lemma Suc_diff_eq_diff_pred: "0 < n ==> Suc m - n = m - (n - 1)" +lemma Suc_diff_eq_diff_pred: "0 < n \ Suc m - n = m - (n - 1)" unfolding One_nat_def by (cases n) simp_all lemma diff_Suc_eq_diff_pred: "m - Suc n = (m - 1) - n" @@ -1180,65 +1181,65 @@ subsubsection \Monotonicity of multiplication\ -lemma mult_le_mono1: "i \ (j::nat) ==> i * k \ j * k" -by (simp add: mult_right_mono) - -lemma mult_le_mono2: "i \ (j::nat) ==> k * i \ k * j" -by (simp add: mult_left_mono) +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::nat) ==> k \ l ==> i * k \ j * l" -by (simp add: mult_mono) - -lemma mult_less_mono1: "(i::nat) < j ==> 0 < k ==> i * k < j * k" -by (simp add: mult_strict_right_mono) +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::nat) * n) = (0 < m & 0 < n)" +lemma nat_0_less_mult_iff [simp]: "0 < m * n \ 0 < m \ 0 < n" for m n :: nat apply (induct m) apply simp apply (case_tac n) apply simp_all done -lemma one_le_mult_iff [simp]: "(Suc 0 \ m * n) = (Suc 0 \ m & Suc 0 \ n)" +lemma one_le_mult_iff [simp]: "Suc 0 \ m * n \ Suc 0 \ m \ Suc 0 \ n" apply (induct m) apply simp apply (case_tac n) apply simp_all done -lemma mult_less_cancel2 [simp]: "((m::nat) * k < n * k) = (0 < k & m < n)" +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, auto) - apply (simp del: le_0_eq add: linorder_not_le [symmetric]) + apply (simp add: linorder_not_le [symmetric]) apply (blast intro: mult_le_mono1) done -lemma mult_less_cancel1 [simp]: "(k * (m::nat) < k * n) = (0 < k & m < n)" -by (simp add: mult.commute [of k]) - -lemma mult_le_cancel1 [simp]: "(k * (m::nat) \ k * n) = (0 < k --> m \ n)" -by (simp add: linorder_not_less [symmetric], auto) - -lemma mult_le_cancel2 [simp]: "((m::nat) * k \ n * k) = (0 < k --> m \ n)" -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::nat)" +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::nat) \ m * (m * m)" +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::nat) = m * n ==> n = 1 | m = 0" +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 nat_less_cases, erule_tac [2] _) @@ -1261,15 +1262,14 @@ 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) +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 @@ -1283,8 +1283,8 @@ consts compow :: "nat \ 'a \ 'a" -abbreviation compower :: "'a \ nat \ 'a" (infixr "^^" 80) where - "f ^^ n \ compow n f" +abbreviation compower :: "'a \ nat \ 'a" (infixr "^^" 80) + where "f ^^ n \ compow n f" notation (latex output) compower ("(_\<^bsup>_\<^esup>)" [1000] 1000) @@ -1292,7 +1292,7 @@ text \\f ^^ n = f o ... o f\, the n-fold composition of \f\\ overloading - funpow == "compow :: nat \ ('a \ 'a) \ ('a \ 'a)" + funpow \ "compow :: nat \ ('a \ 'a) \ ('a \ 'a)" begin primrec funpow :: "nat \ ('a \ 'a) \ 'a \ 'a" where @@ -1304,10 +1304,10 @@ lemma funpow_0 [simp]: "(f ^^ 0) x = x" by simp -lemma funpow_Suc_right: - "f ^^ Suc n = f ^^ n \ f" +lemma funpow_Suc_right: "f ^^ Suc n = f ^^ n \ f" proof (induct n) - case 0 then show ?case by simp + case 0 + then show ?case by simp next fix n assume "f ^^ Suc n = f ^^ n \ f" @@ -1319,27 +1319,23 @@ text \for code generation\ -definition funpow :: "nat \ ('a \ 'a) \ 'a \ 'a" where - funpow_code_def [code_abbrev]: "funpow = compow" +definition funpow :: "nat \ ('a \ 'a) \ 'a \ 'a" + where funpow_code_def [code_abbrev]: "funpow = compow" lemma [code]: - "funpow (Suc n) f = f o funpow n f" + "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" +lemma funpow_add: "f ^^ (m + n) = f ^^ m \ f ^^ n" by (induct m) simp_all -lemma funpow_mult: - fixes f :: "'a \ 'a" - shows "(f ^^ m) ^^ n = f ^^ (m * n)" +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)" +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 o f ^^ 1) x" by (simp only: funpow_add) @@ -1347,9 +1343,7 @@ finally show ?thesis . qed -lemma comp_funpow: - fixes f :: "'a \ 'a" - shows "comp f ^^ n = comp (f ^^ n)" +lemma comp_funpow: "comp f ^^ n = comp (f ^^ n)" for f :: "'a \ 'a" by (induct n) simp_all lemma Suc_funpow[simp]: "Suc ^^ n = (op + n)" @@ -1358,43 +1352,46 @@ lemma id_funpow[simp]: "id ^^ n = id" by (induct n) simp_all -lemma funpow_mono: - fixes f :: "'a \ ('a::lattice)" - shows "mono f \ A \ B \ (f ^^ n) A \ (f ^^ n) B" +lemma funpow_mono: "mono f \ A \ B \ (f ^^ n) A \ (f ^^ n) B" + for f :: "'a \ ('a::lattice)" by (induct n arbitrary: A B) (auto simp del: funpow.simps(2) simp add: funpow_Suc_right mono_def) + subsection \Kleene iteration\ lemma Kleene_iter_lpfp: -assumes "mono f" and "f p \ p" shows "(f^^k) (bot::'a::order_bot) \ p" + assumes "mono f" + and "f p \ p" + shows "(f^^k) (bot::'a::order_bot) \ p" proof(induction k) - case 0 show ?case by simp + case 0 + show ?case by simp next case Suc - from monoD[OF assms(1) Suc] assms(2) - show ?case by simp + from monoD[OF assms(1) Suc] assms(2) show ?case 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) +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 + proof (rule lfp_lowerbound) + show "f ((f^^k) bot) \ (f^^k) bot" + using assms(2) by simp qed -next show "(f^^k) bot \ lfp f" using Kleene_iter_lpfp[OF assms(1)] lfp_unfold[OF assms(1)] by simp qed -lemma mono_pow: - fixes f :: "'a \ 'a::complete_lattice" - shows "mono f \ mono (f ^^ n)" - by (induction n) (auto simp: mono_def) +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" + 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) @@ -1404,13 +1401,14 @@ by (simp add: comp_def) qed have "(f^^n) (lfp f) = lfp f" for n - by (induction n) (auto intro: f lfp_unfold[symmetric]) + by (induct n) (auto intro: f lfp_unfold[symmetric]) 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" + 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) @@ -1420,18 +1418,19 @@ by (simp add: comp_def) qed have "(f^^n) (gfp f) = gfp f" for n - by (induction n) (auto intro: f gfp_unfold[symmetric]) + by (induct n) (auto intro: f gfp_unfold[symmetric]) then show "gfp (f^^Suc n) \ gfp f" by (intro gfp_upperbound) (simp del: funpow.simps) 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" +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" @@ -1448,16 +1447,16 @@ by (induct m) (simp_all add: ac_simps distrib_right) lemma mult_of_nat_commute: "of_nat x * y = y * of_nat x" - by (induction x) (simp_all add: algebra_simps) + 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" +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 + 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" @@ -1475,11 +1474,11 @@ begin lemma of_nat_diff: "n \ m \ of_nat (m - n) = of_nat m - of_nat n" -by (simp add: algebra_simps of_nat_add [symmetric]) + by (simp add: algebra_simps of_nat_add [symmetric]) end -text\Class for unital semirings with characteristic zero. +text \Class for unital semirings with characteristic zero. Includes non-ordered rings like the complex numbers.\ class semiring_char_0 = semiring_1 + @@ -1489,7 +1488,7 @@ 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\ +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]) @@ -1530,12 +1529,12 @@ lemma of_nat_less_imp_less: "of_nat m < of_nat n \ m < n" by simp -text\Every \linordered_semidom\ has characteristic zero.\ - -subclass semiring_char_0 proof -qed (auto intro!: injI simp add: eq_iff) - -text\Special cases where either operand is zero\ +text \Every \linordered_semidom\ 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]) @@ -1615,9 +1614,9 @@ subsection \Further arithmetic facts concerning the natural numbers\ lemma subst_equals: - assumes 1: "t = s" and 2: "u = t" + assumes "t = s" and "u = t" shows "u = s" - using 2 1 by (rule trans) + using assms(2,1) by (rule trans) ML_file "Tools/nat_arith.ML" @@ -1647,7 +1646,10 @@ case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono) -qed (insert \n \ n'\, auto) \ \trivial for @{prop "n = n'"}\ +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'" @@ -1656,27 +1658,26 @@ case True then show ?thesis by (induct n n' rule: less_Suc_induct) (auto intro: mono) -qed (insert \n \ n'\, auto) \ \trivial for @{prop "n = n'"}\ +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" + 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))" +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)" +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: @@ -1684,7 +1685,8 @@ 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 + case 0 + then show ?case by simp next case (Suc k) then have "Suc (f m + k) \ Suc (f (m + k))" by simp @@ -1694,7 +1696,7 @@ qed -text\Subtraction laws, mostly by Clemens Ballarin\ +text \Subtraction laws, mostly by Clemens Ballarin\ lemma diff_less_mono: fixes a b c :: nat @@ -1706,105 +1708,73 @@ then show ?thesis by simp qed -lemma less_diff_conv: - fixes i j k :: nat - shows "i < j - k \ i + k < j" (is "?P \ ?Q") - by (cases "k \ j") - (auto simp add: not_le dest: less_imp_Suc_add le_Suc_ex) - -lemma less_diff_conv2: - fixes j k i :: nat - assumes "k \ j" - shows "j - k < i \ j < i + k" (is "?P \ ?Q") - using assms by (auto dest: le_Suc_ex) - -lemma le_diff_conv: - fixes j k i :: nat - shows "j - k \ i \ j \ i + k" - by (cases "k \ j") - (auto simp add: not_le dest!: less_imp_Suc_add le_Suc_ex) - -lemma diff_diff_cancel [simp]: - fixes i n :: nat - shows "i \ n \ n - (n - i) = i" +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 diff_less [simp]: - fixes i n :: nat - shows "0 < n \ 0 < m \ m - n < m" +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: - fixes m n k :: nat - shows "k \ m \ k \ n \ m - k - (n - k) = m - n" +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: - fixes m n k :: nat - shows "k \ m \ k \ n \ m - k = n - k \ m = n" +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: - fixes m n k :: nat - shows "k \ m \ k \ n \ m - k < n - k \ m < n" +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: - fixes m n k :: nat - shows "k \ m \ k \ n \ m - k \ n - k \ m \ n" +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::nat)" +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: - fixes m n l :: nat - shows "m \ n \ m - l \ n - l" + + +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 add: nat_diff_split) -lemma diff_le_mono2: - fixes m n l :: nat - shows "m \ n \ l - n \ l - m" +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 add: nat_diff_split) -lemma diff_less_mono2: - fixes m n l :: nat - shows "m < n \ m < l \ l - n < l - m" +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 add: nat_diff_split) -lemma diffs0_imp_equal: - fixes m n :: nat - shows "m - n = 0 \ n - m = 0 \ m = n" +lemma diffs0_imp_equal: "m - n = 0 \ n - m = 0 \ m = n" for m n :: nat by (simp split add: nat_diff_split) -lemma min_diff: - fixes m n i :: nat - shows "min (m - i) (n - i) = min m n - i" (is "?lhs = ?rhs") +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: - assumes k_le_n: "\n \ N. k \ (n::nat)" + fixes k :: nat + assumes "\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 k_le_n have "x - k + k = y - k + k" by auto - with a k_le_n show "x = y" by (auto simp add: eq_diff_iff) + 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]: - fixes i j k :: nat - shows "k \ j \ i - (j - k) = i + k - j" +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]: @@ -1842,24 +1812,22 @@ then show ?thesis by simp qed -lemma one_less_mult: - "Suc 0 < n \ Suc 0 < m \ Suc 0 < m * n" +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" +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" +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 \Specialized induction principles that work "backwards":\ lemma inc_induct [consumes 1, case_names base step]: assumes less: "i \ j" - assumes base: "P j" - assumes step: "\n. i \ n \ n < j \ P (Suc n) \ P n" + 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) @@ -1873,7 +1841,7 @@ 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)" + then have "d = j - (n + 1)" by (simp add: diff_diff_eq) then have "d = j - Suc n" by simp @@ -1892,11 +1860,11 @@ 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" - assumes base: "\i. j = Suc i \ P i" - assumes step: "\i. i < j \ P (Suc i) \ P i" + 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) @@ -1922,10 +1890,10 @@ 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)" +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" +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}\ @@ -1933,13 +1901,15 @@ 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 + case 0 + then show ?case by simp next case (Suc j) - from Suc.prems have "i \ j \ i = Suc j" - by (simp add: le_Suc_eq) - then show ?case proof - assume "i \ 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) @@ -1954,70 +1924,62 @@ ultimately show "P (Suc j)" by (rule Suc.prems) next - assume "i = Suc j" + case 2 with \P i\ show "P (Suc j)" by simp qed qed -subsection \ Monotonicity of funpow \ +subsection \Monotonicity of \funpow\\ lemma funpow_increasing: - fixes f :: "'a \ ('a::{lattice, order_top})" + fixes f :: "'a \ 'a::{lattice,order_top}" shows "m \ n \ mono f \ (f ^^ n) \ \ (f ^^ m) \" 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: - fixes f :: "'a \ ('a::{lattice, order_bot})" + fixes f :: "'a \ 'a::{lattice,order_bot}" shows "m \ n \ mono f \ (f ^^ m) \ \ (f ^^ n) \" 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: - fixes Q :: "'a::{lattice, order_bot} \ 'a" + fixes Q :: "'a::{lattice,order_bot} \ 'a" shows "mono Q \ mono (\i. (Q ^^ i) \)" by (auto intro!: funpow_decreasing simp: mono_def) lemma antimono_funpow: - fixes Q :: "'a::{lattice, order_top} \ 'a" + fixes Q :: "'a::{lattice,order_top} \ 'a" shows "mono Q \ antimono (\i. (Q ^^ i) \)" by (auto intro!: funpow_increasing simp: antimono_def) + subsection \The divides relation on @{typ nat}\ -lemma dvd_1_left [iff]: - "Suc 0 dvd k" +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" +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::nat) \ m = 1" +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::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 :: 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::nat)" +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::nat)" +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: @@ -2030,25 +1992,20 @@ 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::nat)" + +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 (subgoal_tac "m * n dvd m * 1") apply (drule dvd_mult_cancel, auto) done -lemma dvd_mult_cancel2: - "0 < m \ n * m dvd m \ n = (1::nat)" +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::nat)" +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: - fixes m n :: nat - shows "0 < m \ m < n \ \ n dvd m" +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: @@ -2061,9 +2018,7 @@ then show ?thesis by (simp add: add.commute [of m]) qed -lemma dvd_minus_self: - fixes m n :: nat - shows "m dvd n - m \ n < m \ m dvd n" +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: @@ -2082,61 +2037,55 @@ subsection \Aliasses\ -lemma nat_mult_1: "(1::nat) * n = n" +lemma nat_mult_1: "1 * n = n" for n :: nat by (fact mult_1_left) -lemma nat_mult_1_right: "n * (1::nat) = n" +lemma nat_mult_1_right: "n * 1 = n" for n :: nat by (fact mult_1_right) -lemma nat_add_left_cancel: - fixes k m n :: nat - shows "k + m = k + n \ m = n" +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: - fixes k m n :: nat - shows "m + k = n + k \ m = n" +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::nat) - n) * k = (m * k) - (n * k)" +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::nat) - n) = (k * m) - (k * n)" +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::nat) ==> m \ n + m - k" - by (fact le_add_diff) \ \FIXME delete\ - -lemma le_diff_conv2: "k \ j ==> (i \ j-k) = (i+k \ (j::nat))" - by (fact le_diff_conv2) \ \FIXME delete\ - -lemma diff_self_eq_0 [simp]: "(m::nat) - m = 0" +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::nat) - j - k = i - (j + k)" +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::nat) - j - k = i - k - j" +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::nat)" +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::nat)" +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::nat)" +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::nat)" +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::nat)" +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)::nat)" +lemma add_mult_distrib2: "k * (m + n) = (k * m) + (k * n)" for k m n :: nat by (fact distrib_left) lemmas nat_distrib = @@ -2151,8 +2100,7 @@ instantiation nat :: size begin -definition size_nat where - [simp, code]: "size (n::nat) = n" +definition size_nat where [simp, code]: "size (n::nat) = n" instance ..