# HG changeset patch # User paulson # Date 1069753023 -3600 # Node ID b963e9cee2a0877f08921315abfa2e3c1f7d88f2 # Parent 08b34c902618a16f49167dec08461c22304eb31b More refinements to Ring_and_Field and numerics. Conversion of Divides_lemmas to Isar script. diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Divides.thy --- a/src/HOL/Divides.thy Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/Divides.thy Tue Nov 25 10:37:03 2003 +0100 @@ -6,7 +6,7 @@ The division operators div, mod and the divides relation "dvd" *) -theory Divides = NatArith files("Divides_lemmas.ML"): +theory Divides = NatArith: (*We use the same class for div and mod; moreover, dvd is defined whenever multiplication is*) @@ -32,7 +32,7 @@ (%f j. if jk. n = m*k" (*This definition helps prove the harder properties of div and mod. It is copied from IntDiv.thy; should it be overloaded?*) @@ -40,11 +40,612 @@ quorem :: "(nat*nat) * (nat*nat) => bool" "quorem == %((a,b), (q,r)). a = b*q + r & - (if 0r & r0)" + + + +subsection{*Initial Lemmas*} + +lemmas wf_less_trans = + def_wfrec [THEN trans, OF eq_reflection wf_pred_nat [THEN wf_trancl], + standard] + +lemma mod_eq: "(%m. m mod n) = + wfrec (trancl pred_nat) (%f j. if j m mod n = (m::nat)" +by (rule mod_eq [THEN wf_less_trans], simp) + +lemma mod_geq: "~ m < (n::nat) ==> m mod n = (m-n) mod n" +apply (case_tac "n=0", simp) +apply (rule mod_eq [THEN wf_less_trans]) +apply (simp add: diff_less cut_apply less_eq) +done + +(*Avoids the ugly ~m m ==> m mod n = (m-n) mod n" +by (simp add: mod_geq not_less_iff_le) + +lemma mod_if: "m mod (n::nat) = (if m m div n = (0::nat)" +by (rule div_eq [THEN wf_less_trans], simp) + +lemma div_geq: "[| 0 m div n = Suc((m-n) div n)" +apply (rule div_eq [THEN wf_less_trans]) +apply (simp add: diff_less cut_apply less_eq) +done + +(*Avoids the ugly ~mm |] ==> m div n = Suc((m-n) div n)" +by (simp add: div_geq not_less_iff_le) + +lemma div_if: "0 m div n = (if m m mod n < (n::nat)" +apply (induct_tac "m" rule: nat_less_induct) +apply (case_tac "na na"}*} +apply (simp add: mod_geq diff_less) +done + +lemma div_mult_self_is_m [simp]: "0 (m*n) div n = (m::nat)" +by (cut_tac m = "m*n" and n = n in mod_div_equality, auto) + +lemma div_mult_self1_is_m [simp]: "0 (n*m) div n = (m::nat)" +by (simp add: mult_commute div_mult_self_is_m) + +(*mod_mult_distrib2 above is the counterpart for remainder*) + + +subsection{*Proving facts about Quotient and Remainder*} + +lemma unique_quotient_lemma: + "[| b*q' + r' \ b*q + r; 0 < b; r < b |] + ==> q' \ (q::nat)" +apply (rule leI) +apply (subst less_iff_Suc_add) +apply (auto simp add: add_mult_distrib2) +done + +lemma unique_quotient: + "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); 0 < b |] + ==> q = q'" +apply (simp add: split_ifs quorem_def) +apply (blast intro: order_antisym + dest: order_eq_refl [THEN unique_quotient_lemma] sym)+ +done + +lemma unique_remainder: + "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); 0 < b |] + ==> r = r'" +apply (subgoal_tac "q = q'") +prefer 2 apply (blast intro: unique_quotient) +apply (simp add: quorem_def) +done + +lemma quorem_div_mod: "0 < b ==> quorem ((a, b), (a div b, a mod b))" +by (auto simp add: quorem_def) + +lemma quorem_div: "[| quorem((a,b),(q,r)); 0 < b |] ==> a div b = q" +by (simp add: quorem_div_mod [THEN unique_quotient]) + +lemma quorem_mod: "[| quorem((a,b),(q,r)); 0 < b |] ==> a mod b = r" +by (simp add: quorem_div_mod [THEN unique_remainder]) + +(** A dividend of zero **) + +lemma div_0 [simp]: "0 div m = (0::nat)" +by (case_tac "m=0", simp_all) + +lemma mod_0 [simp]: "0 mod m = (0::nat)" +by (case_tac "m=0", simp_all) + +(** proving (a*b) div c = a * (b div c) + a * (b mod c) **) + +lemma quorem_mult1_eq: + "[| quorem((b,c),(q,r)); 0 < c |] + ==> quorem ((a*b, c), (a*q + a*r div c, a*r mod c))" +apply (auto simp add: split_ifs mult_ac quorem_def add_mult_distrib2) +done + +lemma div_mult1_eq: "(a*b) div c = a*(b div c) + a*(b mod c) div (c::nat)" +apply (case_tac "c = 0", simp) +apply (blast intro: quorem_div_mod [THEN quorem_mult1_eq, THEN quorem_div]) +done + +lemma mod_mult1_eq: "(a*b) mod c = a*(b mod c) mod (c::nat)" +apply (case_tac "c = 0", simp) +apply (blast intro: quorem_div_mod [THEN quorem_mult1_eq, THEN quorem_mod]) +done + +lemma mod_mult1_eq': "(a*b) mod (c::nat) = ((a mod c) * b) mod c" +apply (rule trans) +apply (rule_tac s = "b*a mod c" in trans) +apply (rule_tac [2] mod_mult1_eq) +apply (simp_all (no_asm) add: mult_commute) +done + +lemma mod_mult_distrib_mod: "(a*b) mod (c::nat) = ((a mod c) * (b mod c)) mod c" +apply (rule mod_mult1_eq' [THEN trans]) +apply (rule mod_mult1_eq) +done + +(** proving (a+b) div c = a div c + b div c + ((a mod c + b mod c) div c) **) + +lemma quorem_add1_eq: + "[| quorem((a,c),(aq,ar)); quorem((b,c),(bq,br)); 0 < c |] + ==> quorem ((a+b, c), (aq + bq + (ar+br) div c, (ar+br) mod c))" +by (auto simp add: split_ifs mult_ac quorem_def add_mult_distrib2) + +(*NOT suitable for rewriting: the RHS has an instance of the LHS*) +lemma div_add1_eq: + "(a+b) div (c::nat) = a div c + b div c + ((a mod c + b mod c) div c)" +apply (case_tac "c = 0", simp) +apply (blast intro: quorem_add1_eq [THEN quorem_div] quorem_div_mod quorem_div_mod) +done + +lemma mod_add1_eq: "(a+b) mod (c::nat) = (a mod c + b mod c) mod c" +apply (case_tac "c = 0", simp) +apply (blast intro: quorem_div_mod quorem_div_mod + quorem_add1_eq [THEN quorem_mod]) +done + + +subsection{*Proving @{term "a div (b*c) = (a div b) div c"}*} + +(** first, a lemma to bound the remainder **) + +lemma mod_lemma: "[| (0::nat) < c; r < b |] ==> b * (q mod c) + r < b * c" +apply (cut_tac m = q and n = c in mod_less_divisor) +apply (drule_tac [2] m = "q mod c" in less_imp_Suc_add, auto) +apply (erule_tac P = "%x. ?lhs < ?rhs x" in ssubst) +apply (simp add: add_mult_distrib2) +done -use "Divides_lemmas.ML" +lemma quorem_mult2_eq: "[| quorem ((a,b), (q,r)); 0 < b; 0 < c |] + ==> quorem ((a, b*c), (q div c, b*(q mod c) + r))" +apply (auto simp add: mult_ac quorem_def add_mult_distrib2 [symmetric] mod_lemma) +done + +lemma div_mult2_eq: "a div (b*c) = (a div b) div (c::nat)" +apply (case_tac "b=0", simp) +apply (case_tac "c=0", simp) +apply (force simp add: quorem_div_mod [THEN quorem_mult2_eq, THEN quorem_div]) +done + +lemma mod_mult2_eq: "a mod (b*c) = b*(a div b mod c) + a mod (b::nat)" +apply (case_tac "b=0", simp) +apply (case_tac "c=0", simp) +apply (auto simp add: mult_commute quorem_div_mod [THEN quorem_mult2_eq, THEN quorem_mod]) +done + + +subsection{*Cancellation of Common Factors in Division*} + +lemma div_mult_mult_lemma: + "[| (0::nat) < b; 0 < c |] ==> (c*a) div (c*b) = a div b" +by (auto simp add: div_mult2_eq) + +lemma div_mult_mult1 [simp]: "(0::nat) < c ==> (c*a) div (c*b) = a div b" +apply (case_tac "b = 0") +apply (auto simp add: linorder_neq_iff [of b] div_mult_mult_lemma) +done + +lemma div_mult_mult2 [simp]: "(0::nat) < c ==> (a*c) div (b*c) = a div b" +apply (drule div_mult_mult1) +apply (auto simp add: mult_commute) +done + + +(*Distribution of Factors over Remainders: + +Could prove these as in Integ/IntDiv.ML, but we already have +mod_mult_distrib and mod_mult_distrib2 above! + +Goal "(c*a) mod (c*b) = (c::nat) * (a mod b)" +qed "mod_mult_mult1"; + +Goal "(a*c) mod (b*c) = (a mod b) * (c::nat)"; +qed "mod_mult_mult2"; + ***) + +subsection{*Further Facts about Quotient and Remainder*} + +lemma div_1 [simp]: "m div Suc 0 = m" +apply (induct_tac "m") +apply (simp_all (no_asm_simp) add: div_geq) +done + +lemma div_self [simp]: "0 n div n = (1::nat)" +by (simp add: div_geq) + +lemma div_add_self2: "0 (m+n) div n = Suc (m div n)" +apply (subgoal_tac " (n + m) div n = Suc ((n+m-n) div n) ") +apply (simp add: add_commute) +apply (subst div_geq [symmetric], simp_all) +done + +lemma div_add_self1: "0 (n+m) div n = Suc (m div n)" +by (simp add: add_commute div_add_self2) + +lemma div_mult_self1 [simp]: "!!n::nat. 0 (m + k*n) div n = k + m div n" +apply (subst div_add1_eq) +apply (subst div_mult1_eq, simp) +done + +lemma div_mult_self2 [simp]: "0 (m + n*k) div n = k + m div (n::nat)" +by (simp add: mult_commute div_mult_self1) + + +(* Monotonicity of div in first argument *) +lemma div_le_mono [rule_format (no_asm)]: + "\m::nat. m \ n --> (m div k) \ (n div k)" +apply (case_tac "k=0", simp) +apply (induct_tac "n" rule: nat_less_induct, clarify) +apply (case_tac "n= k *) +apply (case_tac "m=k *) +apply (simp add: div_geq diff_less diff_le_mono) +done + +(* Antimonotonicity of div in second argument *) +lemma div_le_mono2: "!!m::nat. [| 0n |] ==> (k div n) \ (k div m)" +apply (subgoal_tac "0 (k-m) div n") + prefer 2 + apply (blast intro: div_le_mono diff_le_mono2) +apply (rule le_trans, simp) +apply (simp add: diff_less) +done + +lemma div_le_dividend [simp]: "m div n \ (m::nat)" +apply (case_tac "n=0", simp) +apply (subgoal_tac "m div n \ m div 1", simp) +apply (rule div_le_mono2) +apply (simp_all (no_asm_simp)) +done + +(* Similar for "less than" *) +lemma div_less_dividend [rule_format, simp]: + "!!n::nat. 1 0 < m --> m div n < m" +apply (induct_tac "m" rule: nat_less_induct) +apply (rename_tac "m") +apply (case_tac "m Suc(na) *) +apply (simp add: not_less_iff_le le_Suc_eq mod_geq) +apply (auto simp add: Suc_diff_le diff_less le_mod_geq) +done + + +subsection{*The Divides Relation*} + +lemma dvdI [intro?]: "n = m * k ==> m dvd n" +by (unfold dvd_def, blast) + +lemma dvdE [elim?]: "!!P. [|m dvd n; !!k. n = m*k ==> P|] ==> P" +by (unfold dvd_def, blast) -declare dvdI [intro?] dvdE [elim?] dvd_trans [trans] +lemma dvd_0_right [iff]: "m dvd (0::nat)" +apply (unfold dvd_def) +apply (blast intro: mult_0_right [symmetric]) +done + +lemma dvd_0_left: "0 dvd m ==> m = (0::nat)" +by (force simp add: dvd_def) + +lemma dvd_0_left_iff [iff]: "(0 dvd (m::nat)) = (m = 0)" +by (blast intro: dvd_0_left) + +lemma dvd_1_left [iff]: "Suc 0 dvd k" +by (unfold dvd_def, simp) + +lemma dvd_1_iff_1 [simp]: "(m dvd Suc 0) = (m = Suc 0)" +by (simp add: dvd_def) + +lemma dvd_refl [simp]: "m dvd (m::nat)" +apply (unfold dvd_def) +apply (blast intro: mult_1_right [symmetric]) +done + +lemma dvd_trans [trans]: "[| m dvd n; n dvd p |] ==> m dvd (p::nat)" +apply (unfold dvd_def) +apply (blast intro: mult_assoc) +done + +lemma dvd_anti_sym: "[| m dvd n; n dvd m |] ==> m = (n::nat)" +apply (unfold dvd_def) +apply (force dest: mult_eq_self_implies_10 simp add: mult_assoc mult_eq_1_iff) +done + +lemma dvd_add: "[| k dvd m; k dvd n |] ==> k dvd (m+n :: nat)" +apply (unfold dvd_def) +apply (blast intro: add_mult_distrib2 [symmetric]) +done + +lemma dvd_diff: "[| k dvd m; k dvd n |] ==> k dvd (m-n :: nat)" +apply (unfold dvd_def) +apply (blast intro: diff_mult_distrib2 [symmetric]) +done + +lemma dvd_diffD: "[| k dvd m-n; k dvd n; n\m |] ==> k dvd (m::nat)" +apply (erule not_less_iff_le [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)" +by (drule_tac m = m in dvd_diff, auto) + +lemma dvd_mult: "k dvd n ==> k dvd (m*n :: nat)" +apply (unfold dvd_def) +apply (blast intro: mult_left_commute) +done + +lemma dvd_mult2: "k dvd m ==> k dvd (m*n :: nat)" +apply (subst mult_commute) +apply (erule dvd_mult) +done + +(* k dvd (m*k) *) +declare dvd_refl [THEN dvd_mult, iff] dvd_refl [THEN dvd_mult2, iff] + +lemma dvd_reduce: "(k dvd n + k) = (k dvd (n::nat))" +apply (rule iffI) +apply (erule_tac [2] dvd_add) +apply (rule_tac [2] dvd_refl) +apply (subgoal_tac "n = (n+k) -k") + prefer 2 apply simp +apply (erule ssubst) +apply (erule dvd_diff) +apply (rule dvd_refl) +done + +lemma dvd_mod: "!!n::nat. [| f dvd m; f dvd n |] ==> f dvd m mod n" +apply (unfold dvd_def) +apply (case_tac "n=0", auto) +apply (blast intro: mod_mult_distrib2 [symmetric]) +done + +lemma dvd_mod_imp_dvd: "[| (k::nat) dvd m mod n; k dvd n |] ==> k dvd m" +apply (subgoal_tac "k dvd (m div n) *n + m mod n") + apply (simp add: mod_div_equality) +apply (simp only: dvd_add dvd_mult) +done + +lemma dvd_mod_iff: "k dvd n ==> ((k::nat) dvd m mod n) = (k dvd m)" +by (blast intro: dvd_mod_imp_dvd dvd_mod) + +lemma dvd_mult_cancel: "!!k::nat. [| k*m dvd k*n; 0 m dvd n" +apply (unfold dvd_def) +apply (erule exE) +apply (simp add: mult_ac) +done + +lemma dvd_mult_cancel1: "0 (m*n dvd m) = (n = (1::nat))" +apply auto +apply (subgoal_tac "m*n dvd m*1") +apply (drule dvd_mult_cancel, auto) +done + +lemma dvd_mult_cancel2: "0 (n*m dvd m) = (n = (1::nat))" +apply (subst mult_commute) +apply (erule dvd_mult_cancel1) +done + +lemma mult_dvd_mono: "[| i dvd m; j dvd n|] ==> i*j dvd (m*n :: nat)" +apply (unfold dvd_def, clarify) +apply (rule_tac x = "k*ka" in exI) +apply (simp add: mult_ac) +done + +lemma dvd_mult_left: "(i*j :: nat) dvd k ==> i dvd k" +by (simp add: dvd_def mult_assoc, blast) + +lemma dvd_mult_right: "(i*j :: nat) dvd k ==> j dvd k" +apply (unfold dvd_def, clarify) +apply (rule_tac x = "i*k" in exI) +apply (simp add: mult_ac) +done + +lemma dvd_imp_le: "[| k dvd n; 0 < n |] ==> k \ (n::nat)" +apply (unfold dvd_def, clarify) +apply (simp_all (no_asm_use) add: zero_less_mult_iff) +apply (erule conjE) +apply (rule le_trans) +apply (rule_tac [2] le_refl [THEN mult_le_mono]) +apply (erule_tac [2] Suc_leI, simp) +done + +lemma dvd_eq_mod_eq_0: "!!k::nat. (k dvd n) = (n mod k = 0)" +apply (unfold dvd_def) +apply (case_tac "k=0", simp, safe) +apply (simp add: mult_commute) +apply (rule_tac t = n and n1 = k in mod_div_equality [THEN subst]) +apply (subst mult_commute, simp) +done + +lemma dvd_mult_div_cancel: "n dvd m ==> n * (m div n) = (m::nat)" +apply (subgoal_tac "m mod n = 0") + apply (simp add: mult_div_cancel) +apply (simp only: dvd_eq_mod_eq_0) +done + +lemma mod_eq_0_iff: "(m mod d = 0) = (\q::nat. m = d*q)" +by (auto simp add: dvd_eq_mod_eq_0 [symmetric] dvd_def) +declare mod_eq_0_iff [THEN iffD1, dest!] + +(*Loses information, namely we also have r \q::nat. m = r + q*d" +apply (cut_tac m = m in mod_div_equality) +apply (simp only: add_ac) +apply (blast intro: sym) +done + lemma split_div: "P(n div k :: nat) = @@ -87,7 +688,7 @@ qed lemma split_div_lemma: - "0 < n \ (n * q <= m \ m < n * (Suc q)) = (q = ((m::nat) div n))" + "0 < n \ (n * q \ m \ m < n * (Suc q)) = (q = ((m::nat) div n))" apply (rule iffI) apply (rule_tac a=m and r = "m - n * q" and r' = "m mod n" in unique_quotient) apply (simp_all add: quorem_def, arith) @@ -103,7 +704,7 @@ theorem split_div': "P ((m::nat) div n) = ((n = 0 \ P 0) \ - (\q. (n * q <= m \ m < n * (Suc q)) \ P q))" + (\q. (n * q \ m \ m < n * (Suc q)) \ P q))" apply (case_tac "0 < n") apply (simp only: add: split_div_lemma) apply (simp_all add: DIVISION_BY_ZERO_DIV) @@ -148,6 +749,106 @@ apply arith done +ML +{* +val div_def = thm "div_def" +val mod_def = thm "mod_def" +val dvd_def = thm "dvd_def" +val quorem_def = thm "quorem_def" + +val wf_less_trans = thm "wf_less_trans"; +val mod_eq = thm "mod_eq"; +val div_eq = thm "div_eq"; +val DIVISION_BY_ZERO_DIV = thm "DIVISION_BY_ZERO_DIV"; +val DIVISION_BY_ZERO_MOD = thm "DIVISION_BY_ZERO_MOD"; +val mod_less = thm "mod_less"; +val mod_geq = thm "mod_geq"; +val le_mod_geq = thm "le_mod_geq"; +val mod_if = thm "mod_if"; +val mod_1 = thm "mod_1"; +val mod_self = thm "mod_self"; +val mod_add_self2 = thm "mod_add_self2"; +val mod_add_self1 = thm "mod_add_self1"; +val mod_mult_self1 = thm "mod_mult_self1"; +val mod_mult_self2 = thm "mod_mult_self2"; +val mod_mult_distrib = thm "mod_mult_distrib"; +val mod_mult_distrib2 = thm "mod_mult_distrib2"; +val mod_mult_self_is_0 = thm "mod_mult_self_is_0"; +val mod_mult_self1_is_0 = thm "mod_mult_self1_is_0"; +val div_less = thm "div_less"; +val div_geq = thm "div_geq"; +val le_div_geq = thm "le_div_geq"; +val div_if = thm "div_if"; +val mod_div_equality = thm "mod_div_equality"; +val mod_div_equality2 = thm "mod_div_equality2"; +val div_mod_equality = thm "div_mod_equality"; +val div_mod_equality2 = thm "div_mod_equality2"; +val mult_div_cancel = thm "mult_div_cancel"; +val mod_less_divisor = thm "mod_less_divisor"; +val div_mult_self_is_m = thm "div_mult_self_is_m"; +val div_mult_self1_is_m = thm "div_mult_self1_is_m"; +val unique_quotient_lemma = thm "unique_quotient_lemma"; +val unique_quotient = thm "unique_quotient"; +val unique_remainder = thm "unique_remainder"; +val div_0 = thm "div_0"; +val mod_0 = thm "mod_0"; +val div_mult1_eq = thm "div_mult1_eq"; +val mod_mult1_eq = thm "mod_mult1_eq"; +val mod_mult1_eq' = thm "mod_mult1_eq'"; +val mod_mult_distrib_mod = thm "mod_mult_distrib_mod"; +val div_add1_eq = thm "div_add1_eq"; +val mod_add1_eq = thm "mod_add1_eq"; +val mod_lemma = thm "mod_lemma"; +val div_mult2_eq = thm "div_mult2_eq"; +val mod_mult2_eq = thm "mod_mult2_eq"; +val div_mult_mult_lemma = thm "div_mult_mult_lemma"; +val div_mult_mult1 = thm "div_mult_mult1"; +val div_mult_mult2 = thm "div_mult_mult2"; +val div_1 = thm "div_1"; +val div_self = thm "div_self"; +val div_add_self2 = thm "div_add_self2"; +val div_add_self1 = thm "div_add_self1"; +val div_mult_self1 = thm "div_mult_self1"; +val div_mult_self2 = thm "div_mult_self2"; +val div_le_mono = thm "div_le_mono"; +val div_le_mono2 = thm "div_le_mono2"; +val div_le_dividend = thm "div_le_dividend"; +val div_less_dividend = thm "div_less_dividend"; +val mod_Suc = thm "mod_Suc"; +val dvdI = thm "dvdI"; +val dvdE = thm "dvdE"; +val dvd_0_right = thm "dvd_0_right"; +val dvd_0_left = thm "dvd_0_left"; +val dvd_0_left_iff = thm "dvd_0_left_iff"; +val dvd_1_left = thm "dvd_1_left"; +val dvd_1_iff_1 = thm "dvd_1_iff_1"; +val dvd_refl = thm "dvd_refl"; +val dvd_trans = thm "dvd_trans"; +val dvd_anti_sym = thm "dvd_anti_sym"; +val dvd_add = thm "dvd_add"; +val dvd_diff = thm "dvd_diff"; +val dvd_diffD = thm "dvd_diffD"; +val dvd_diffD1 = thm "dvd_diffD1"; +val dvd_mult = thm "dvd_mult"; +val dvd_mult2 = thm "dvd_mult2"; +val dvd_reduce = thm "dvd_reduce"; +val dvd_mod = thm "dvd_mod"; +val dvd_mod_imp_dvd = thm "dvd_mod_imp_dvd"; +val dvd_mod_iff = thm "dvd_mod_iff"; +val dvd_mult_cancel = thm "dvd_mult_cancel"; +val dvd_mult_cancel1 = thm "dvd_mult_cancel1"; +val dvd_mult_cancel2 = thm "dvd_mult_cancel2"; +val mult_dvd_mono = thm "mult_dvd_mono"; +val dvd_mult_left = thm "dvd_mult_left"; +val dvd_mult_right = thm "dvd_mult_right"; +val dvd_imp_le = thm "dvd_imp_le"; +val dvd_eq_mod_eq_0 = thm "dvd_eq_mod_eq_0"; +val dvd_mult_div_cancel = thm "dvd_mult_div_cancel"; +val mod_eq_0_iff = thm "mod_eq_0_iff"; +val mod_eqD = thm "mod_eqD"; +*} + + (* lemma split_div: assumes m: "m \ 0" diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Divides_lemmas.ML --- a/src/HOL/Divides_lemmas.ML Mon Nov 24 15:33:07 2003 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,734 +0,0 @@ -(* Title: HOL/Divides.ML - ID: $Id$ - Author: Lawrence C Paulson, Cambridge University Computer Laboratory - Copyright 1993 University of Cambridge - -The division operators div, mod and the divides relation "dvd" -*) - -(* ML legacy bindings *) - -val div_def = thm "div_def"; -val mod_def = thm "mod_def"; -val dvd_def = thm "dvd_def"; -val quorem_def = thm "quorem_def"; - -structure Divides = -struct - val div_def = div_def - val mod_def = mod_def - val dvd_def = dvd_def - val quorem_def = quorem_def -end; - -(** Less-then properties **) - -bind_thm ("wf_less_trans", [eq_reflection, wf_pred_nat RS wf_trancl] MRS - def_wfrec RS trans); - -Goal "(%m. m mod n) = wfrec (trancl pred_nat) \ -\ (%f j. if j m mod n = (m::nat)"; -by (rtac (mod_eq RS wf_less_trans) 1); -by (Asm_simp_tac 1); -qed "mod_less"; -Addsimps [mod_less]; - -Goal "~ m < (n::nat) ==> m mod n = (m-n) mod n"; -by (div_undefined_case_tac "n=0" 1); -by (rtac (mod_eq RS wf_less_trans) 1); -by (asm_simp_tac (simpset() addsimps [diff_less, cut_apply, less_eq]) 1); -qed "mod_geq"; - -(*Avoids the ugly ~m m mod n = (m-n) mod n"; -by (asm_simp_tac (simpset() addsimps [mod_geq, not_less_iff_le]) 1); -qed "le_mod_geq"; - -Goal "m mod (n::nat) = (if m m div n = (0::nat)"; -by (rtac (div_eq RS wf_less_trans) 1); -by (Asm_simp_tac 1); -qed "div_less"; -Addsimps [div_less]; - -Goal "[| 0 m div n = Suc((m-n) div n)"; -by (rtac (div_eq RS wf_less_trans) 1); -by (asm_simp_tac (simpset() addsimps [diff_less, cut_apply, less_eq]) 1); -qed "div_geq"; - -(*Avoids the ugly ~m m div n = Suc((m-n) div n)"; -by (asm_simp_tac (simpset() addsimps [div_geq, not_less_iff_le]) 1); -qed "le_div_geq"; - -Goal "0 m div n = (if m m mod n < (n::nat)"; -by (induct_thm_tac nat_less_induct "m" 1); -by (case_tac "na (m*n) div n = (m::nat)"; -by (cut_inst_tac [("m", "m*n"),("n","n")] mod_div_equality 1); -by Auto_tac; -qed "div_mult_self_is_m"; - -Goal "0 (n*m) div n = (m::nat)"; -by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self_is_m]) 1); -qed "div_mult_self1_is_m"; -Addsimps [div_mult_self_is_m, div_mult_self1_is_m]; - -(*mod_mult_distrib2 above is the counterpart for remainder*) - - -(*** Proving facts about div and mod using quorem ***) - -Goal "[| b*q' + r' <= b*q + r; 0 < b; r < b |] \ -\ ==> q' <= (q::nat)"; -by (rtac leI 1); -by (stac less_iff_Suc_add 1); -by (auto_tac (claset(), simpset() addsimps [add_mult_distrib2])); -qed "unique_quotient_lemma"; - -Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); 0 < b |] \ -\ ==> q = q'"; -by (asm_full_simp_tac - (simpset() addsimps split_ifs @ [Divides.quorem_def]) 1); -by (REPEAT - (blast_tac (claset() addIs [order_antisym] - addDs [order_eq_refl RS unique_quotient_lemma, - sym]) 1)); -qed "unique_quotient"; - -Goal "[| quorem ((a,b), (q,r)); quorem ((a,b), (q',r')); 0 < b |] \ -\ ==> r = r'"; -by (subgoal_tac "q = q'" 1); -by (blast_tac (claset() addIs [unique_quotient]) 2); -by (asm_full_simp_tac (simpset() addsimps [Divides.quorem_def]) 1); -qed "unique_remainder"; - -Goal "0 < b ==> quorem ((a, b), (a div b, a mod b))"; -by (auto_tac - (claset() addEs [sym], - simpset() addsimps mult_ac@[Divides.quorem_def])); -qed "quorem_div_mod"; - -Goal "[| quorem((a,b),(q,r)); 0 < b |] ==> a div b = q"; -by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_quotient]) 1); -qed "quorem_div"; - -Goal "[| quorem((a,b),(q,r)); 0 < b |] ==> a mod b = r"; -by (asm_simp_tac (simpset() addsimps [quorem_div_mod RS unique_remainder]) 1); -qed "quorem_mod"; - -(** A dividend of zero **) - -Goal "0 div m = (0::nat)"; -by (div_undefined_case_tac "m=0" 1); -by (Asm_simp_tac 1); -qed "div_0"; - -Goal "0 mod m = (0::nat)"; -by (div_undefined_case_tac "m=0" 1); -by (Asm_simp_tac 1); -qed "mod_0"; -Addsimps [div_0, mod_0]; - -(** proving (a*b) div c = a * (b div c) + a * (b mod c) **) - -Goal "[| quorem((b,c),(q,r)); 0 < c |] \ -\ ==> quorem ((a*b, c), (a*q + a*r div c, a*r mod c))"; -by (auto_tac - (claset(), - simpset() addsimps split_ifs@mult_ac@ - [Divides.quorem_def, add_mult_distrib2])); -val lemma = result(); - -Goal "(a*b) div c = a*(b div c) + a*(b mod c) div (c::nat)"; -by (div_undefined_case_tac "c = 0" 1); -by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_div]) 1); -qed "div_mult1_eq"; - -Goal "(a*b) mod c = a*(b mod c) mod (c::nat)"; -by (div_undefined_case_tac "c = 0" 1); -by (blast_tac (claset() addIs [quorem_div_mod RS lemma RS quorem_mod]) 1); -qed "mod_mult1_eq"; - -Goal "(a*b) mod (c::nat) = ((a mod c) * b) mod c"; -by (rtac trans 1); -by (res_inst_tac [("s","b*a mod c")] trans 1); -by (rtac mod_mult1_eq 2); -by (ALLGOALS (simp_tac (simpset() addsimps [mult_commute]))); -qed "mod_mult1_eq'"; - -Goal "(a*b) mod (c::nat) = ((a mod c) * (b mod c)) mod c"; -by (rtac (mod_mult1_eq' RS trans) 1); -by (rtac mod_mult1_eq 1); -qed "mod_mult_distrib_mod"; - -(** proving (a+b) div c = a div c + b div c + ((a mod c + b mod c) div c) **) - -Goal "[| quorem((a,c),(aq,ar)); quorem((b,c),(bq,br)); 0 < c |] \ -\ ==> quorem ((a+b, c), (aq + bq + (ar+br) div c, (ar+br) mod c))"; -by (auto_tac - (claset(), - simpset() addsimps split_ifs@mult_ac@ - [Divides.quorem_def, add_mult_distrib2])); -val lemma = result(); - -(*NOT suitable for rewriting: the RHS has an instance of the LHS*) -Goal "(a+b) div (c::nat) = a div c + b div c + ((a mod c + b mod c) div c)"; -by (div_undefined_case_tac "c = 0" 1); -by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod] - MRS lemma RS quorem_div]) 1); -qed "div_add1_eq"; - -Goal "(a+b) mod (c::nat) = (a mod c + b mod c) mod c"; -by (div_undefined_case_tac "c = 0" 1); -by (blast_tac (claset() addIs [[quorem_div_mod,quorem_div_mod] - MRS lemma RS quorem_mod]) 1); -qed "mod_add1_eq"; - - -(*** proving a div (b*c) = (a div b) div c ***) - -(** first, a lemma to bound the remainder **) - -Goal "[| (0::nat) < c; r < b |] ==> b * (q mod c) + r < b * c"; -by (cut_inst_tac [("m","q"),("n","c")] mod_less_divisor 1); -by (dres_inst_tac [("m","q mod c")] less_imp_Suc_add 2); -by Auto_tac; -by (eres_inst_tac [("P","%x. ?lhs < ?rhs x")] ssubst 1); -by (asm_simp_tac (simpset() addsimps [add_mult_distrib2]) 1); -val mod_lemma = result(); - -Goal "[| quorem ((a,b), (q,r)); 0 < b; 0 < c |] \ -\ ==> quorem ((a, b*c), (q div c, b*(q mod c) + r))"; -by (auto_tac - (claset(), - simpset() addsimps mult_ac@ - [Divides.quorem_def, add_mult_distrib2 RS sym, - mod_lemma])); -val lemma = result(); - -Goal "a div (b*c) = (a div b) div (c::nat)"; -by (div_undefined_case_tac "b=0" 1); -by (div_undefined_case_tac "c=0" 1); -by (force_tac (claset(), - simpset() addsimps [quorem_div_mod RS lemma RS quorem_div]) 1); -qed "div_mult2_eq"; - -Goal "a mod (b*c) = b*(a div b mod c) + a mod (b::nat)"; -by (div_undefined_case_tac "b=0" 1); -by (div_undefined_case_tac "c=0" 1); -by (auto_tac (claset(), - simpset() addsimps [mult_commute, - quorem_div_mod RS lemma RS quorem_mod])); -qed "mod_mult2_eq"; - - -(*** Cancellation of common factors in "div" ***) - -Goal "[| (0::nat) < b; 0 < c |] ==> (c*a) div (c*b) = a div b"; -by (stac div_mult2_eq 1); -by Auto_tac; -val lemma1 = result(); - -Goal "(0::nat) < c ==> (c*a) div (c*b) = a div b"; -by (div_undefined_case_tac "b = 0" 1); -by (auto_tac - (claset(), - simpset() addsimps [read_instantiate [("x", "b")] linorder_neq_iff, - lemma1, lemma2])); -qed "div_mult_mult1"; - -Goal "(0::nat) < c ==> (a*c) div (b*c) = a div b"; -by (dtac div_mult_mult1 1); -by (auto_tac (claset(), simpset() addsimps [mult_commute])); -qed "div_mult_mult2"; - -Addsimps [div_mult_mult1, div_mult_mult2]; - - -(*** Distribution of factors over "mod" - -Could prove these as in Integ/IntDiv.ML, but we already have -mod_mult_distrib and mod_mult_distrib2 above! - -Goal "(c*a) mod (c*b) = (c::nat) * (a mod b)"; -qed "mod_mult_mult1"; - -Goal "(a*c) mod (b*c) = (a mod b) * (c::nat)"; -qed "mod_mult_mult2"; - ***) - -(*** Further facts about div and mod ***) - -Goal "m div Suc 0 = m"; -by (induct_tac "m" 1); -by (ALLGOALS (asm_simp_tac (simpset() addsimps [div_geq]))); -qed "div_1"; -Addsimps [div_1]; - -Goal "0 n div n = (1::nat)"; -by (asm_simp_tac (simpset() addsimps [div_geq]) 1); -qed "div_self"; -Addsimps [div_self]; - -Goal "0 (m+n) div n = Suc (m div n)"; -by (subgoal_tac "(n + m) div n = Suc ((n+m-n) div n)" 1); -by (stac (div_geq RS sym) 2); -by (ALLGOALS (asm_full_simp_tac (simpset() addsimps [add_commute]))); -qed "div_add_self2"; - -Goal "0 (n+m) div n = Suc (m div n)"; -by (asm_simp_tac (simpset() addsimps [add_commute, div_add_self2]) 1); -qed "div_add_self1"; - -Goal "!!n::nat. 0 (m + k*n) div n = k + m div n"; -by (stac div_add1_eq 1); -by (stac div_mult1_eq 1); -by (Asm_simp_tac 1); -qed "div_mult_self1"; - -Goal "0 (m + n*k) div n = k + m div (n::nat)"; -by (asm_simp_tac (simpset() addsimps [mult_commute, div_mult_self1]) 1); -qed "div_mult_self2"; - -Addsimps [div_mult_self1, div_mult_self2]; - -(* Monotonicity of div in first argument *) -Goal "ALL m::nat. m <= n --> (m div k) <= (n div k)"; -by (div_undefined_case_tac "k=0" 1); -by (induct_thm_tac nat_less_induct "n" 1); -by (Clarify_tac 1); -by (case_tac "n= k *) -by (case_tac "m=k *) -by (asm_simp_tac (simpset() addsimps [div_geq, diff_less, diff_le_mono]) 1); -qed_spec_mp "div_le_mono"; - -(* Antimonotonicity of div in second argument *) -Goal "!!m::nat. [| 0 (k div n) <= (k div m)"; -by (subgoal_tac "0 (0 < m) --> (m div n < m)"; -by (induct_thm_tac nat_less_induct "m" 1); -by (rename_tac "m" 1); -by (case_tac "m m dvd n"; -by (Blast_tac 1); -qed "dvdI"; - -Goalw [dvd_def] "!!P. [|m dvd n; !!k. n = m*k ==> P|] ==> P"; -by (Blast_tac 1); -qed "dvdE"; - -Goalw [dvd_def] "m dvd (0::nat)"; -by (blast_tac (claset() addIs [mult_0_right RS sym]) 1); -qed "dvd_0_right"; -AddIffs [dvd_0_right]; - -Goalw [dvd_def] "0 dvd m ==> m = (0::nat)"; -by Auto_tac; -qed "dvd_0_left"; - -Goal "(0 dvd (m::nat)) = (m = 0)"; -by (blast_tac (claset() addIs [dvd_0_left]) 1); -qed "dvd_0_left_iff"; -AddIffs [dvd_0_left_iff]; - -Goalw [dvd_def] "Suc 0 dvd k"; -by (Simp_tac 1); -qed "dvd_1_left"; -AddIffs [dvd_1_left]; - -Goal "(m dvd Suc 0) = (m = Suc 0)"; -by (simp_tac (simpset() addsimps [dvd_def]) 1); -qed "dvd_1_iff_1"; -Addsimps [dvd_1_iff_1]; - -Goalw [dvd_def] "m dvd (m::nat)"; -by (blast_tac (claset() addIs [mult_1_right RS sym]) 1); -qed "dvd_refl"; -Addsimps [dvd_refl]; - -Goalw [dvd_def] "[| m dvd n; n dvd p |] ==> m dvd (p::nat)"; -by (blast_tac (claset() addIs [mult_assoc] ) 1); -qed "dvd_trans"; - -Goalw [dvd_def] "[| m dvd n; n dvd m |] ==> m = (n::nat)"; -by (force_tac (claset() addDs [mult_eq_self_implies_10], - simpset() addsimps [mult_assoc, mult_eq_1_iff]) 1); -qed "dvd_anti_sym"; - -Goalw [dvd_def] "[| k dvd m; k dvd n |] ==> k dvd (m+n :: nat)"; -by (blast_tac (claset() addIs [add_mult_distrib2 RS sym]) 1); -qed "dvd_add"; - -Goalw [dvd_def] "[| k dvd m; k dvd n |] ==> k dvd (m-n :: nat)"; -by (blast_tac (claset() addIs [diff_mult_distrib2 RS sym]) 1); -qed "dvd_diff"; - -Goal "[| k dvd m-n; k dvd n; n<=m |] ==> k dvd (m::nat)"; -by (etac (not_less_iff_le RS iffD2 RS add_diff_inverse RS subst) 1); -by (blast_tac (claset() addIs [dvd_add]) 1); -qed "dvd_diffD"; - -Goal "[| k dvd m-n; k dvd m; n<=m |] ==> k dvd (n::nat)"; -by (dres_inst_tac [("m","m")] dvd_diff 1); -by Auto_tac; -qed "dvd_diffD1"; - -Goalw [dvd_def] "k dvd n ==> k dvd (m*n :: nat)"; -by (blast_tac (claset() addIs [mult_left_commute]) 1); -qed "dvd_mult"; - -Goal "k dvd m ==> k dvd (m*n :: nat)"; -by (stac mult_commute 1); -by (etac dvd_mult 1); -qed "dvd_mult2"; - -(* k dvd (m*k) *) -AddIffs [dvd_refl RS dvd_mult, dvd_refl RS dvd_mult2]; - -Goal "(k dvd n + k) = (k dvd (n::nat))"; -by (rtac iffI 1); -by (etac dvd_add 2); -by (rtac dvd_refl 2); -by (subgoal_tac "n = (n+k)-k" 1); -by (Simp_tac 2); -by (etac ssubst 1); -by (etac dvd_diff 1); -by (rtac dvd_refl 1); -qed "dvd_reduce"; - -Goalw [dvd_def] "!!n::nat. [| f dvd m; f dvd n |] ==> f dvd m mod n"; -by (div_undefined_case_tac "n=0" 1); -by Auto_tac; -by (blast_tac (claset() addIs [mod_mult_distrib2 RS sym]) 1); -qed "dvd_mod"; - -Goal "[| (k::nat) dvd m mod n; k dvd n |] ==> k dvd m"; -by (subgoal_tac "k dvd (m div n)*n + m mod n" 1); -by (asm_simp_tac (HOL_basic_ss addsimps [dvd_add, dvd_mult]) 2); -by (asm_full_simp_tac (simpset() addsimps [mod_div_equality]) 1); -qed "dvd_mod_imp_dvd"; - -Goal "k dvd n ==> ((k::nat) dvd m mod n) = (k dvd m)"; -by (blast_tac (claset() addIs [dvd_mod_imp_dvd, dvd_mod]) 1); -qed "dvd_mod_iff"; - -Goalw [dvd_def] "!!k::nat. [| k*m dvd k*n; 0 m dvd n"; -by (etac exE 1); -by (asm_full_simp_tac (simpset() addsimps mult_ac) 1); -qed "dvd_mult_cancel"; - -Goal "0 (m*n dvd m) = (n = (1::nat))"; -by Auto_tac; -by (subgoal_tac "m*n dvd m*1" 1); -by (dtac dvd_mult_cancel 1); -by Auto_tac; -qed "dvd_mult_cancel1"; - -Goal "0 (n*m dvd m) = (n = (1::nat))"; -by (stac mult_commute 1); -by (etac dvd_mult_cancel1 1); -qed "dvd_mult_cancel2"; - -Goalw [dvd_def] "[| i dvd m; j dvd n|] ==> i*j dvd (m*n :: nat)"; -by (Clarify_tac 1); -by (res_inst_tac [("x","k*ka")] exI 1); -by (asm_simp_tac (simpset() addsimps mult_ac) 1); -qed "mult_dvd_mono"; - -Goalw [dvd_def] "(i*j :: nat) dvd k ==> i dvd k"; -by (full_simp_tac (simpset() addsimps [mult_assoc]) 1); -by (Blast_tac 1); -qed "dvd_mult_left"; - -Goalw [dvd_def] "(i*j :: nat) dvd k ==> j dvd k"; -by (Clarify_tac 1); -by (res_inst_tac [("x","i*k")] exI 1); -by (simp_tac (simpset() addsimps mult_ac) 1); -qed "dvd_mult_right"; - -Goalw [dvd_def] "[| k dvd n; 0 < n |] ==> k <= (n::nat)"; -by (Clarify_tac 1); -by (ALLGOALS (full_simp_tac (simpset() addsimps [zero_less_mult_iff]))); -by (etac conjE 1); -by (rtac le_trans 1); -by (rtac (le_refl RS mult_le_mono) 2); -by (etac Suc_leI 2); -by (Simp_tac 1); -qed "dvd_imp_le"; - -Goalw [dvd_def] "!!k::nat. (k dvd n) = (n mod k = 0)"; -by (div_undefined_case_tac "k=0" 1); -by Safe_tac; -by (asm_simp_tac (simpset() addsimps [mult_commute]) 1); -by (res_inst_tac [("t","n"),("n1","k")] (mod_div_equality RS subst) 1); -by (stac mult_commute 1); -by (Asm_simp_tac 1); -qed "dvd_eq_mod_eq_0"; - -Goal "n dvd m ==> n * (m div n) = (m::nat)"; -by (subgoal_tac "m mod n = 0" 1); - by (asm_full_simp_tac (simpset() addsimps [mult_div_cancel]) 1); -by (asm_full_simp_tac (HOL_basic_ss addsimps [dvd_eq_mod_eq_0]) 1); -qed "dvd_mult_div_cancel"; - -Goal "(m mod d = 0) = (EX q::nat. m = d*q)"; -by (auto_tac (claset(), - simpset() addsimps [dvd_eq_mod_eq_0 RS sym, dvd_def])); -qed "mod_eq_0_iff"; -AddSDs [mod_eq_0_iff RS iffD1]; - -(*Loses information, namely we also have r EX q::nat. m = r + q*d"; -by (cut_inst_tac [("m","m")] mod_div_equality 1); -by (full_simp_tac (HOL_basic_ss addsimps add_ac) 1); -by (blast_tac (claset() addIs [sym]) 1); -qed "mod_eqD"; diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Integ/Int.thy --- a/src/HOL/Integ/Int.thy Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/Integ/Int.thy Tue Nov 25 10:37:03 2003 +0100 @@ -239,15 +239,6 @@ subsection{*Instances of the equations above, for zero*} -(*instantiate a variable to zero and simplify*) - -declare zless_zminus [of 0, simplified, simp] -declare zminus_zless [of _ 0, simplified, simp] -declare zle_zminus [of 0, simplified, simp] -declare zminus_zle [of _ 0, simplified, simp] -declare equation_zminus [of 0, simplified, simp] -declare zminus_equation [of _ 0, simplified, simp] - lemma negative_zless_0: "- (int (Suc n)) < 0" by (simp add: zless_def) @@ -343,53 +334,10 @@ apply (auto simp add: nat_mono_iff linorder_not_less) done -(* a case theorem distinguishing non-negative and negative int *) - -lemma int_cases: - "[|!! n. z = int n ==> P; !! n. z = - (int (Suc n)) ==> P |] ==> P" -apply (case_tac "neg z") -apply (fast dest!: negD) -apply (drule not_neg_nat [symmetric], auto) -done - - -subsection{*Monotonicity of Multiplication*} - -lemma zmult_zle_mono1_lemma: "i \ (j::int) ==> i * int k \ j * int k" -apply (induct_tac "k") -apply (simp_all (no_asm_simp) add: int_Suc zadd_zmult_distrib2 zadd_zle_mono int_Suc0_eq_1) -done - -lemma zmult_zle_mono1: "[| i \ j; (0::int) \ k |] ==> i*k \ j*k" -apply (rule_tac t = k in not_neg_nat [THEN subst]) -apply (erule_tac [2] zmult_zle_mono1_lemma) -apply (simp (no_asm_use) add: not_neg_eq_ge_0) -done -lemma zmult_zle_mono1_neg: "[| i \ j; k \ (0::int) |] ==> j*k \ i*k" -apply (rule zminus_zle_zminus [THEN iffD1]) -apply (simp add: zmult_zminus_right [symmetric] zmult_zle_mono1 zle_zminus) -done - -lemma zmult_zle_mono2: "[| i \ j; (0::int) \ k |] ==> k*i \ k*j" -apply (drule zmult_zle_mono1) -apply (simp_all add: zmult_commute) -done +subsection{*Strict Monotonicity of Multiplication*} -lemma zmult_zle_mono2_neg: "[| i \ j; k \ (0::int) |] ==> k*j \ k*i" -apply (drule zmult_zle_mono1_neg) -apply (simp_all add: zmult_commute) -done - -(* \ monotonicity, BOTH arguments*) -lemma zmult_zle_mono: "[| i \ j; k \ l; (0::int) \ j; (0::int) \ k |] ==> i*k \ j*l" -apply (erule zmult_zle_mono1 [THEN order_trans], assumption) -apply (erule zmult_zle_mono2, assumption) -done - - -subsection{*strict, in 1st argument; proof is by induction on k>0*} - +text{*strict, in 1st argument; proof is by induction on k>0*} lemma zmult_zless_mono2_lemma: "i 0 int k * i < int k * j" apply (induct_tac "k", simp) apply (simp add: int_Suc) @@ -423,6 +371,25 @@ show "\i\ = (if i < 0 then -i else i)" by (simp only: zabs_def) qed +subsection{*Monotonicity of Multiplication*} + +lemma zmult_zle_mono1: "[| i \ j; (0::int) \ k |] ==> i*k \ j*k" + by (rule mult_right_mono) + +lemma zmult_zle_mono1_neg: "[| i \ j; k \ (0::int) |] ==> j*k \ i*k" + by (rule mult_right_mono_neg) + +lemma zmult_zle_mono2: "[| i \ j; (0::int) \ k |] ==> k*i \ k*j" + by (rule mult_left_mono) + +lemma zmult_zle_mono2_neg: "[| i \ j; k \ (0::int) |] ==> k*j \ k*i" + by (rule mult_left_mono_neg) + +(* \ monotonicity, BOTH arguments*) +lemma zmult_zle_mono: + "[| i \ j; k \ l; (0::int) \ j; (0::int) \ k |] ==> i*k \ j*l" + by (rule mult_mono) + lemma zmult_zless_mono1: "[| i i*k < j*k" by (rule Ring_and_Field.mult_strict_right_mono) @@ -467,6 +434,16 @@ apply (auto simp add: int_Suc symmetric zdiff_def) done +(* a case theorem distinguishing non-negative and negative int *) + +lemma int_cases: + "[|!! n. z = int n ==> P; !! n. z = - (int (Suc n)) ==> P |] ==> P" +apply (case_tac "neg z") +apply (fast dest!: negD) +apply (drule not_neg_nat [symmetric], auto) +done + + ML diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Integ/nat_simprocs.ML --- a/src/HOL/Integ/nat_simprocs.ML Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/Integ/nat_simprocs.ML Tue Nov 25 10:37:03 2003 +0100 @@ -211,7 +211,7 @@ (*Simplify 1*n and n*1 to n*) val add_0s = map rename_numerals [add_0, add_0_right]; -val mult_1s = map rename_numerals [mult_1, mult_1_right]; +val mult_1s = map rename_numerals [thm"nat_mult_1", thm"nat_mult_1_right"]; (*Final simplification: cancel + and *; replace Numeral0 by 0 and Numeral1 by 1*) diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/IsaMakefile --- a/src/HOL/IsaMakefile Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/IsaMakefile Tue Nov 25 10:37:03 2003 +0100 @@ -80,7 +80,7 @@ $(SRC)/TFL/dcterm.ML $(SRC)/TFL/post.ML \ $(SRC)/TFL/rules.ML $(SRC)/TFL/tfl.ML $(SRC)/TFL/thms.ML $(SRC)/TFL/thry.ML \ $(SRC)/TFL/usyntax.ML $(SRC)/TFL/utils.ML \ - Datatype.thy Datatype_Universe.ML Datatype_Universe.thy Divides_lemmas.ML \ + Datatype.thy Datatype_Universe.ML Datatype_Universe.thy \ Divides.thy Extraction.thy Finite_Set.ML Finite_Set.thy \ Fun.thy Gfp.ML Gfp.thy \ Hilbert_Choice.thy Hilbert_Choice_lemmas.ML HOL.ML \ diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Nat.thy --- a/src/HOL/Nat.thy Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/Nat.thy Tue Nov 25 10:37:03 2003 +0100 @@ -21,7 +21,7 @@ axioms -- {* the axiom of infinity in 2 parts *} inj_Suc_Rep: "inj Suc_Rep" - Suc_Rep_not_Zero_Rep: "Suc_Rep x ~= Zero_Rep" + Suc_Rep_not_Zero_Rep: "Suc_Rep x \ Zero_Rep" subsection {* Type nat *} @@ -64,7 +64,7 @@ less_def: "m < n == (m, n) : trancl pred_nat" - le_def: "m <= (n::nat) == ~ (n < m)" + le_def: "m \ (n::nat) == ~ (n < m)" text {* Induction *} @@ -91,14 +91,14 @@ text {* Distinctness of constructors *} -lemma Suc_not_Zero [iff]: "Suc m ~= 0" +lemma Suc_not_Zero [iff]: "Suc m \ 0" apply (unfold Zero_nat_def Suc_def) apply (rule inj_on_Abs_Nat [THEN inj_on_contraD]) apply (rule Suc_Rep_not_Zero_Rep) apply (rule Rep_Nat Nat.Suc_RepI Nat.Zero_RepI)+ done -lemma Zero_not_Suc [iff]: "0 ~= Suc m" +lemma Zero_not_Suc [iff]: "0 \ Suc m" by (rule not_sym, rule Suc_not_Zero not_sym) lemma Suc_neq_Zero: "Suc m = 0 ==> R" @@ -127,7 +127,7 @@ apply (erule arg_cong) done -lemma nat_not_singleton: "(ALL x. x = (0::nat)) = False" +lemma nat_not_singleton: "(\x. x = (0::nat)) = False" by auto text {* @{typ nat} is a datatype *} @@ -137,10 +137,10 @@ inject Suc_Suc_eq induction nat_induct -lemma n_not_Suc_n: "n ~= Suc n" +lemma n_not_Suc_n: "n \ Suc n" by (induct n) simp_all -lemma Suc_n_not_n: "Suc t ~= t" +lemma Suc_n_not_n: "Suc t \ t" by (rule not_sym, rule n_not_Suc_n) text {* A special form of induction for reasoning @@ -219,9 +219,9 @@ lemma less_irrefl [elim!]: "(n::nat) < n ==> R" by (rule notE, rule less_not_refl) -lemma less_not_refl2: "n < m ==> m ~= (n::nat)" by blast +lemma less_not_refl2: "n < m ==> m \ (n::nat)" by blast -lemma less_not_refl3: "(s::nat) < t ==> s ~= t" +lemma less_not_refl3: "(s::nat) < t ==> s \ t" by (rule not_sym, rule less_not_refl2) lemma lessE: @@ -268,7 +268,7 @@ apply (blast intro: Suc_mono less_SucI elim: lessE) done -lemma nat_neq_iff: "((m::nat) ~= n) = (m < n | n < m)" +lemma nat_neq_iff: "((m::nat) \ n) = (m < n | n < m)" using less_linear by blast lemma nat_less_cases: assumes major: "(m::nat) < n ==> P n m" @@ -284,7 +284,7 @@ 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" apply (simp add: nat_neq_iff) apply (blast elim!: less_irrefl less_SucE elim: less_asym) done @@ -324,7 +324,7 @@ text {* Complete induction, aka course-of-values induction *} lemma nat_less_induct: - assumes prem: "!!n. ALL m::nat. m < n --> P m ==> P n" shows "P n" + assumes prem: "!!n. \m::nat. m < n --> P m ==> P n" shows "P n" apply (rule_tac a=n in wf_induct) apply (rule wf_pred_nat [THEN wf_trancl]) apply (rule prem) @@ -336,119 +336,119 @@ subsection {* Properties of "less than or equal" *} text {* Was @{text le_eq_less_Suc}, but this orientation is more useful *} -lemma less_Suc_eq_le: "(m < Suc n) = (m <= n)" +lemma less_Suc_eq_le: "(m < Suc n) = (m \ n)" by (unfold le_def, rule not_less_eq [symmetric]) -lemma le_imp_less_Suc: "m <= n ==> m < Suc n" +lemma le_imp_less_Suc: "m \ n ==> m < Suc n" by (rule less_Suc_eq_le [THEN iffD2]) -lemma le0 [iff]: "(0::nat) <= n" +lemma le0 [iff]: "(0::nat) \ n" by (unfold le_def, rule not_less0) -lemma Suc_n_not_le_n: "~ Suc n <= n" +lemma Suc_n_not_le_n: "~ Suc n \ n" by (simp add: le_def) -lemma le_0_eq [iff]: "((i::nat) <= 0) = (i = 0)" +lemma le_0_eq [iff]: "((i::nat) \ 0) = (i = 0)" by (induct i) (simp_all add: le_def) -lemma le_Suc_eq: "(m <= Suc n) = (m <= n | m = Suc n)" +lemma le_Suc_eq: "(m \ Suc n) = (m \ n | m = Suc n)" by (simp del: less_Suc_eq_le 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], rules+) -lemma leI: "~ n < m ==> m <= (n::nat)" by (simp add: le_def) +lemma leI: "~ n < m ==> m \ (n::nat)" by (simp add: le_def) -lemma leD: "m <= n ==> ~ n < (m::nat)" +lemma leD: "m \ n ==> ~ n < (m::nat)" by (simp add: le_def) lemmas leE = leD [elim_format] -lemma not_less_iff_le: "(~ n < m) = (m <= (n::nat))" +lemma not_less_iff_le: "(~ n < m) = (m \ (n::nat))" by (blast intro: leI elim: leE) -lemma not_leE: "~ m <= n ==> n<(m::nat)" +lemma not_leE: "~ m \ n ==> n<(m::nat)" by (simp add: le_def) -lemma not_le_iff_less: "(~ n <= m) = (m < (n::nat))" +lemma not_le_iff_less: "(~ n \ m) = (m < (n::nat))" by (simp add: le_def) -lemma Suc_leI: "m < n ==> Suc(m) <= n" +lemma Suc_leI: "m < n ==> Suc(m) \ n" apply (simp add: le_def less_Suc_eq) apply (blast elim!: less_irrefl less_asym) done -- {* formerly called lessD *} -lemma Suc_leD: "Suc(m) <= n ==> m <= n" +lemma Suc_leD: "Suc(m) \ n ==> m \ n" by (simp add: le_def less_Suc_eq) text {* Stronger version of @{text Suc_leD} *} -lemma Suc_le_lessD: "Suc m <= n ==> m < n" +lemma Suc_le_lessD: "Suc m \ n ==> m < n" apply (simp add: le_def less_Suc_eq) using less_linear apply blast done -lemma Suc_le_eq: "(Suc m <= n) = (m < n)" +lemma Suc_le_eq: "(Suc m \ n) = (m < n)" by (blast intro: Suc_leI Suc_le_lessD) -lemma le_SucI: "m <= n ==> m <= Suc n" +lemma le_SucI: "m \ n ==> m \ Suc n" by (unfold le_def) (blast dest: Suc_lessD) -lemma less_imp_le: "m < n ==> m <= (n::nat)" +lemma less_imp_le: "m < n ==> m \ (n::nat)" by (unfold le_def) (blast elim: less_asym) -text {* For instance, @{text "(Suc m < Suc n) = (Suc m <= n) = (m < n)"} *} +text {* For instance, @{text "(Suc m < Suc n) = (Suc m \ n) = (m < n)"} *} lemmas le_simps = less_imp_le less_Suc_eq_le Suc_le_eq -text {* Equivalence of @{term "m <= n"} and @{term "m < n | m = n"} *} +text {* Equivalence of @{term "m \ n"} and @{term "m < n | m = n"} *} -lemma le_imp_less_or_eq: "m <= n ==> m < n | m = (n::nat)" +lemma le_imp_less_or_eq: "m \ n ==> m < n | m = (n::nat)" apply (unfold le_def) using less_linear apply (blast elim: less_irrefl less_asym) done -lemma less_or_eq_imp_le: "m < n | m = n ==> m <= (n::nat)" +lemma less_or_eq_imp_le: "m < n | m = n ==> m \ (n::nat)" apply (unfold le_def) using less_linear apply (blast elim!: less_irrefl elim: less_asym) done -lemma le_eq_less_or_eq: "(m <= (n::nat)) = (m < n | m=n)" +lemma le_eq_less_or_eq: "(m \ (n::nat)) = (m < n | m=n)" by (rules intro: less_or_eq_imp_le le_imp_less_or_eq) text {* Useful with @{text Blast}. *} -lemma eq_imp_le: "(m::nat) = n ==> m <= n" +lemma eq_imp_le: "(m::nat) = n ==> m \ n" by (rule less_or_eq_imp_le, rule disjI2) -lemma le_refl: "n <= (n::nat)" +lemma le_refl: "n \ (n::nat)" by (simp add: le_eq_less_or_eq) -lemma le_less_trans: "[| i <= j; j < k |] ==> i < (k::nat)" +lemma le_less_trans: "[| i \ j; j < k |] ==> i < (k::nat)" by (blast dest!: le_imp_less_or_eq intro: less_trans) -lemma less_le_trans: "[| i < j; j <= k |] ==> i < (k::nat)" +lemma less_le_trans: "[| i < j; j \ k |] ==> i < (k::nat)" by (blast dest!: le_imp_less_or_eq intro: less_trans) -lemma le_trans: "[| i <= j; j <= k |] ==> i <= (k::nat)" +lemma le_trans: "[| i \ j; j \ k |] ==> i \ (k::nat)" by (blast dest!: le_imp_less_or_eq intro: less_or_eq_imp_le less_trans) -lemma le_anti_sym: "[| m <= n; n <= m |] ==> m = (n::nat)" +lemma le_anti_sym: "[| m \ n; n \ m |] ==> m = (n::nat)" by (blast dest!: le_imp_less_or_eq elim!: less_irrefl elim: less_asym) -lemma Suc_le_mono [iff]: "(Suc n <= Suc m) = (n <= m)" +lemma Suc_le_mono [iff]: "(Suc n \ Suc m) = (n \ m)" by (simp add: le_simps) text {* Axiom @{text order_less_le} of class @{text order}: *} -lemma nat_less_le: "((m::nat) < n) = (m <= n & m ~= n)" +lemma nat_less_le: "((m::nat) < n) = (m \ n & m \ n)" by (simp add: le_def nat_neq_iff) (blast elim!: less_asym) -lemma le_neq_implies_less: "(m::nat) <= n ==> m ~= n ==> m < n" +lemma le_neq_implies_less: "(m::nat) \ n ==> m \ n ==> m < n" by (rule iffD2, rule nat_less_le, rule conjI) text {* Axiom @{text linorder_linear} of class @{text linorder}: *} -lemma nat_le_linear: "(m::nat) <= n | n <= m" +lemma nat_le_linear: "(m::nat) \ n | n \ m" apply (simp add: le_eq_less_or_eq) using less_linear apply blast @@ -460,10 +460,10 @@ text {* Rewrite @{term "n < Suc m"} to @{term "n = m"} - if @{term "~ n < m"} or @{term "m <= n"} hold. + if @{term "~ n < m"} or @{term "m \ n"} hold. Not suitable as default simprules because they often lead to looping *} -lemma le_less_Suc_eq: "m <= n ==> (n < Suc m) = (n = m)" +lemma le_less_Suc_eq: "m \ n ==> (n < Suc m) = (n = m)" by (rule not_less_less_Suc_eq, rule leD) lemmas not_less_simps = not_less_less_Suc_eq le_less_Suc_eq @@ -526,20 +526,20 @@ lemma def_nat_rec_Suc: "(!!n. f n == nat_rec c h n) ==> f (Suc n) = h n (f n)" by simp -lemma not0_implies_Suc: "n ~= 0 ==> EX m. n = Suc m" +lemma not0_implies_Suc: "n \ 0 ==> \m. n = Suc m" by (case_tac n) simp_all -lemma gr_implies_not0: "!!n::nat. m n ~= 0" +lemma gr_implies_not0: "!!n::nat. m n \ 0" by (case_tac n) simp_all -lemma neq0_conv [iff]: "!!n::nat. (n ~= 0) = (0 < n)" +lemma neq0_conv [iff]: "!!n::nat. (n \ 0) = (0 < n)" by (case_tac n) simp_all text {* This theorem is useful with @{text blast} *} lemma gr0I: "((n::nat) = 0 ==> False) ==> 0 < n" by (rule iffD1, rule neq0_conv, rules) -lemma gr0_conv_Suc: "(0 < n) = (EX m. n = Suc m)" +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)" @@ -547,11 +547,11 @@ apply (rule ccontr, simp_all) done -lemma Suc_le_D: "(Suc n <= m') ==> (? m. m' = Suc m)" +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 | (EX j. m = Suc j & j < n))" +lemma less_Suc_eq_0_disj: "(m < Suc n) = (m = 0 | (\j. m = Suc j & j < n))" by (case_tac m) simp_all lemma nat_induct2: "P 0 ==> P (Suc 0) ==> (!!k. P k ==> P (Suc (Suc k))) ==> P n" @@ -567,21 +567,21 @@ lemmas Least_le = wellorder_Least_le lemmas not_less_Least = wellorder_not_less_Least -lemma Least_Suc: "[| P n; ~ P 0 |] ==> (LEAST n. P n) = Suc (LEAST m. P(Suc m))" +lemma Least_Suc: + "[| P n; ~ P 0 |] ==> (LEAST n. P n) = Suc (LEAST m. P(Suc m))" apply (case_tac "n", 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 (subgoal_tac " (LEAST x. P x) \ Suc (LEAST x. P (Suc x))") apply (erule_tac [2] Least_le) apply (case_tac "LEAST x. P x", 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)" - apply (erule (1) Least_Suc [THEN ssubst]) - apply simp - 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) @@ -640,29 +640,26 @@ text {* Associative law for addition *} -lemma add_assoc: "(m + n) + k = m + ((n + k)::nat)" +lemma nat_add_assoc: "(m + n) + k = m + ((n + k)::nat)" by (induct m) simp_all text {* Commutative law for addition *} -lemma add_commute: "m + n = n + (m::nat)" +lemma nat_add_commute: "m + n = n + (m::nat)" by (induct m) simp_all -lemma add_left_commute: "x + (y + z) = y + ((x + z)::nat)" +lemma nat_add_left_commute: "x + (y + z) = y + ((x + z)::nat)" apply (rule mk_left_commute [of "op +"]) - apply (rule add_assoc) - apply (rule add_commute) + apply (rule nat_add_assoc) + apply (rule nat_add_commute) done -text {* Addition is an AC-operator *} -lemmas add_ac = add_assoc add_commute add_left_commute - lemma add_left_cancel [simp]: "(k + m = k + n) = (m = (n::nat))" by (induct k) simp_all lemma add_right_cancel [simp]: "(m + k = n + k) = (m=(n::nat))" by (induct k) simp_all -lemma add_left_cancel_le [simp]: "(k + m <= k + n) = (m<=(n::nat))" +lemma add_left_cancel_le [simp]: "(k + m \ k + n) = (m\(n::nat))" by (induct k) simp_all lemma add_left_cancel_less [simp]: "(k + m < k + n) = (m<(n::nat))" @@ -684,24 +681,114 @@ lemma add_eq_self_zero: "!!m::nat. m + n = m ==> n = 0" apply (drule add_0_right [THEN ssubst]) - apply (simp add: add_assoc del: add_0_right) + apply (simp add: nat_add_assoc del: add_0_right) done -subsection {* Additional theorems about "less than" *} +subsection {* Monotonicity of Addition *} + +text {* strict, in 1st argument *} +lemma add_less_mono1: "i < j ==> i + k < j + (k::nat)" + by (induct k) simp_all -text {* Deleted @{text less_natE}; instead use @{text "less_imp_Suc_add RS exE"} *} -lemma less_imp_Suc_add: "m < n ==> (EX k. n = Suc (m + k))" +text {* strict, in both arguments *} +lemma add_less_mono: "[|i < j; k < l|] ==> i + k < j + (l::nat)" + apply (rule add_less_mono1 [THEN less_trans], assumption+) + apply (induct_tac j, simp_all) + done + +text {* Deleted @{text less_natE}; use @{text "less_imp_Suc_add RS exE"} *} +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!: add_0_right [symmetric] add_Suc_right [symmetric]) done -lemma le_add2: "n <= ((m + n)::nat)" + +subsection {* Multiplication *} + +text {* right annihilation in product *} +lemma mult_0_right [simp]: "(m::nat) * 0 = 0" + by (induct m) simp_all + +text {* right successor law for multiplication *} +lemma mult_Suc_right [simp]: "m * Suc n = m + (m * n)" + by (induct m) (simp_all add: nat_add_left_commute) + +text {* Commutative law for multiplication *} +lemma nat_mult_commute: "m * n = n * (m::nat)" + by (induct m) simp_all + +text {* addition distributes over multiplication *} +lemma add_mult_distrib: "(m + n) * k = (m * k) + ((n * k)::nat)" + by (induct m) (simp_all add: nat_add_assoc nat_add_left_commute) + +lemma add_mult_distrib2: "k * (m + n) = (k * m) + ((k * n)::nat)" + by (induct m) (simp_all add: nat_add_assoc) + +text {* Associative law for multiplication *} +lemma nat_mult_assoc: "(m * n) * k = m * ((n * k)::nat)" + by (induct m) (simp_all add: add_mult_distrib) + +lemma mult_is_0 [simp]: "((m::nat) * n = 0) = (m=0 | n=0)" + apply (induct_tac m) + apply (induct_tac [2] n, simp_all) + done + +text {* strict, in 1st argument; proof is by induction on @{text "k > 0"} *} +lemma mult_less_mono2: "(i::nat) < j ==> 0 < k ==> k * i < k * j" + apply (erule_tac m1 = 0 in less_imp_Suc_add [THEN exE], simp) + apply (induct_tac x) + apply (simp_all add: add_less_mono) + done + +text{*The Naturals Form an Ordered Semiring*} +instance nat :: ordered_semiring +proof + fix i j k :: nat + show "(i + j) + k = i + (j + k)" by (rule nat_add_assoc) + show "i + j = j + i" by (rule nat_add_commute) + show "0 + i = i" by simp + show "(i * j) * k = i * (j * k)" by (rule nat_mult_assoc) + show "i * j = j * i" by (rule nat_mult_commute) + show "1 * i = i" by simp + show "(i + j) * k = i * k + j * k" by (simp add: add_mult_distrib) + show "0 \ (1::nat)" by simp + show "i \ j ==> k + i \ k + j" by simp + show "i < j ==> 0 < k ==> k * i < k * j" by (simp add: mult_less_mono2) +qed + +lemma nat_mult_1: "(1::nat) * n = n" + by simp + +lemma nat_mult_1_right: "n * (1::nat) = n" + by simp + + +subsection {* Additional theorems about "less than" *} + +text {* A [clumsy] way of lifting @{text "<"} + monotonicity to @{text "\"} monotonicity *} +lemma less_mono_imp_le_mono: + assumes lt_mono: "!!i j::nat. i < j ==> f i < f j" + and le: "i \ j" shows "f i \ ((f j)::nat)" using le + apply (simp add: order_le_less) + apply (blast intro!: lt_mono) + done + +text {* non-strict, in 1st argument *} +lemma add_le_mono1: "i \ j ==> i + k \ 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)" apply (induct m, simp_all) apply (erule le_SucI) done -lemma le_add1: "n <= ((n + m)::nat)" +lemma le_add1: "n \ ((n + m)::nat)" apply (simp add: add_ac) apply (rule le_add2) done @@ -712,14 +799,14 @@ 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) = (EX k. n = Suc (m + k))" +lemma less_iff_Suc_add: "(m < n) = (\k. n = Suc (m + k))" by (rules intro!: less_add_Suc1 less_imp_Suc_add) -lemma trans_le_add1: "(i::nat) <= j ==> i <= j + m" +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" +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" @@ -741,15 +828,15 @@ lemma not_add_less2 [iff]: "~ (j + i < (i::nat))" by (simp add: add_commute not_add_less1) -lemma add_leD1: "m + k <= n ==> m <= (n::nat)" +lemma add_leD1: "m + k \ n ==> m \ (n::nat)" by (induct k) (simp_all add: le_simps) -lemma add_leD2: "m + k <= n ==> k <= (n::nat)" +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" +lemma add_leE: "(m::nat) + k \ n ==> (m \ n ==> k \ n ==> R) ==> R" by (blast dest: add_leD1 add_leD2) text {* needs @{text "!!k"} for @{text add_ac} to work *} @@ -758,106 +845,6 @@ simp add: less_iff_Suc_add add_Suc_right [symmetric] add_ac) -subsection {* Monotonicity of Addition *} - -text {* strict, in 1st argument *} -lemma add_less_mono1: "i < j ==> i + k < 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)" - apply (rule add_less_mono1 [THEN less_trans], assumption+) - apply (induct_tac j, simp_all) - done - -text {* A [clumsy] way of lifting @{text "<"} - monotonicity to @{text "<="} monotonicity *} -lemma less_mono_imp_le_mono: - assumes lt_mono: "!!i j::nat. i < j ==> f i < f j" - and le: "i <= j" shows "f i <= ((f j)::nat)" using le - apply (simp add: order_le_less) - apply (blast intro!: lt_mono) - done - -text {* non-strict, in 1st argument *} -lemma add_le_mono1: "i <= j ==> i + k <= j + (k::nat)" - apply (rule_tac f = "%j. j + k" in less_mono_imp_le_mono) - apply (erule add_less_mono1, assumption) - done - -text {* non-strict, in both arguments *} -lemma add_le_mono: "[| i <= j; k <= l |] ==> i + k <= j + (l::nat)" - apply (erule add_le_mono1 [THEN le_trans]) - apply (simp add: add_commute) - done - - -subsection {* Multiplication *} - -text {* right annihilation in product *} -lemma mult_0_right [simp]: "(m::nat) * 0 = 0" - by (induct m) simp_all - -text {* right successor law for multiplication *} -lemma mult_Suc_right [simp]: "m * Suc n = m + (m * n)" - by (induct m) (simp_all add: add_ac) - -lemma mult_1: "(1::nat) * n = n" by simp - -lemma mult_1_right: "n * (1::nat) = n" by simp - -text {* Commutative law for multiplication *} -lemma mult_commute: "m * n = n * (m::nat)" - by (induct m) simp_all - -text {* addition distributes over multiplication *} -lemma add_mult_distrib: "(m + n) * k = (m * k) + ((n * k)::nat)" - by (induct m) (simp_all add: add_ac) - -lemma add_mult_distrib2: "k * (m + n) = (k * m) + ((k * n)::nat)" - by (induct m) (simp_all add: add_ac) - -text {* Associative law for multiplication *} -lemma mult_assoc: "(m * n) * k = m * ((n * k)::nat)" - by (induct m) (simp_all add: add_mult_distrib) - -lemma mult_left_commute: "x * (y * z) = y * ((x * z)::nat)" - apply (rule mk_left_commute [of "op *"]) - apply (rule mult_assoc) - apply (rule mult_commute) - done - -lemmas mult_ac = mult_assoc mult_commute mult_left_commute - -lemma mult_is_0 [simp]: "((m::nat) * n = 0) = (m=0 | n=0)" - apply (induct_tac m) - apply (induct_tac [2] n, simp_all) - done - -text {* strict, in 1st argument; proof is by induction on @{text "k > 0"} *} -lemma mult_less_mono2: "(i::nat) < j ==> 0 < k ==> k * i < k * j" - apply (erule_tac m1 = 0 in less_imp_Suc_add [THEN exE], simp) - apply (induct_tac x) - apply (simp_all add: add_less_mono) - done - -text{*The Naturals Form an Ordered Semiring*} -instance nat :: ordered_semiring -proof - fix i j k :: nat - show "(i + j) + k = i + (j + k)" by (rule add_assoc) - show "i + j = j + i" by (rule add_commute) - show "0 + i = i" by simp - show "(i * j) * k = i * (j * k)" by (rule mult_assoc) - show "i * j = j * i" by (rule mult_commute) - show "1 * i = i" by simp - show "(i + j) * k = i * k + j * k" by (simp add: add_mult_distrib) - show "0 \ (1::nat)" by simp - show "i \ j ==> k + i \ k + j" by simp - show "i < j ==> 0 < k ==> k * i < k * j" by (simp add: mult_less_mono2) -qed - - subsection {* Difference *} @@ -865,20 +852,20 @@ by (induct m) simp_all text {* Addition is the inverse of subtraction: - if @{term "n <= m"} then @{term "n + (m - n) = m"}. *} + if @{term "n \ m"} then @{term "n + (m - n) = m"}. *} lemma add_diff_inverse: "~ m < n ==> n + (m - n) = (m::nat)" by (induct m n rule: diff_induct) simp_all -lemma le_add_diff_inverse [simp]: "n <= m ==> n + (m - n) = (m::nat)" +lemma le_add_diff_inverse [simp]: "n \ m ==> n + (m - n) = (m::nat)" by (simp add: add_diff_inverse not_less_iff_le) -lemma le_add_diff_inverse2 [simp]: "n <= m ==> (m - n) + n = (m::nat)" +lemma le_add_diff_inverse2 [simp]: "n \ m ==> (m - n) + n = (m::nat)" by (simp add: le_add_diff_inverse add_commute) subsection {* More results about difference *} -lemma Suc_diff_le: "n <= m ==> Suc m - n = Suc (m - n)" +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" @@ -887,7 +874,7 @@ apply (simp_all add: less_Suc_eq) done -lemma diff_le_self [simp]: "m - n <= (m::nat)" +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" @@ -908,10 +895,10 @@ lemma diff_commute: "(i::nat) - j - k = i - k - j" by (simp add: diff_diff_left add_commute) -lemma diff_add_assoc: "k <= (j::nat) ==> (i + j) - k = i + (j - k)" +lemma diff_add_assoc: "k \ (j::nat) ==> (i + j) - k = i + (j - k)" by (induct j k rule: diff_induct) simp_all -lemma diff_add_assoc2: "k <= (j::nat) ==> (j + i) - k = (j - k) + i" +lemma diff_add_assoc2: "k \ (j::nat) ==> (j + i) - k = (j - k) + i" by (simp add: add_commute diff_add_assoc) lemma diff_add_inverse: "(n + m) - n = (m::nat)" @@ -920,21 +907,21 @@ lemma diff_add_inverse2: "(m + n) - n = (m::nat)" by (simp add: diff_add_assoc) -lemma le_imp_diff_is_add: "i <= (j::nat) ==> (j - i = k) = (j = k + i)" +lemma le_imp_diff_is_add: "i \ (j::nat) ==> (j - i = k) = (j = k + i)" apply safe apply (simp_all add: diff_add_inverse2) done -lemma diff_is_0_eq [simp]: "((m::nat) - n = 0) = (m <= n)" +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" +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 less_imp_add_positive: "i < j ==> EX k::nat. 0 < k & i + k = j" +lemma less_imp_add_positive: "i < j ==> \k::nat. 0 < k & i + k = j" apply (rule_tac x = "j - i" in exI) apply (simp (no_asm_simp) add: add_diff_inverse less_not_sym) done @@ -975,16 +962,16 @@ subsection {* Monotonicity of Multiplication *} -lemma mult_le_mono1: "i <= (j::nat) ==> i * k <= j * k" +lemma mult_le_mono1: "i \ (j::nat) ==> i * k \ j * k" by (induct k) (simp_all add: add_le_mono) -lemma mult_le_mono2: "i <= (j::nat) ==> k * i <= k * j" +lemma mult_le_mono2: "i \ (j::nat) ==> k * i \ k * j" apply (drule mult_le_mono1) apply (simp add: mult_commute) done -text {* @{text "<="} monotonicity, BOTH arguments *} -lemma mult_le_mono: "i <= (j::nat) ==> k <= l ==> i * k <= j * l" +text {* @{text "\"} monotonicity, BOTH arguments *} +lemma mult_le_mono: "i \ (j::nat) ==> k \ l ==> i * k \ j * l" apply (erule mult_le_mono1 [THEN le_trans]) apply (erule mult_le_mono2) done @@ -999,7 +986,7 @@ apply (case_tac [2] n, simp_all) done -lemma one_le_mult_iff [simp]: "(Suc 0 <= m * n) = (1 <= m & 1 <= n)" +lemma one_le_mult_iff [simp]: "(Suc 0 \ m * n) = (1 \ m & 1 \ n)" apply (induct m) apply (case_tac [2] n, simp_all) done @@ -1026,10 +1013,10 @@ declare mult_less_cancel2 [simp] -lemma mult_le_cancel1 [simp]: "(k * (m::nat) <= k * n) = (0 < k --> m <= n)" +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)" +lemma mult_le_cancel2 [simp]: "((m::nat) * k \ n * k) = (0 < k --> m \ n)" by (simp add: linorder_not_less [symmetric], auto) lemma mult_cancel2: "(m * k = n * k) = (m = n | (k = (0::nat)))" @@ -1045,7 +1032,7 @@ 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)" +lemma Suc_mult_le_cancel1: "(Suc k * m \ Suc k * n) = (m \ n)" by (subst mult_le_cancel1) simp lemma Suc_mult_cancel1: "(Suc k * m = Suc k * n) = (m = n)" diff -r 08b34c902618 -r b963e9cee2a0 src/HOL/Ring_and_Field.thy --- a/src/HOL/Ring_and_Field.thy Mon Nov 24 15:33:07 2003 +0100 +++ b/src/HOL/Ring_and_Field.thy Tue Nov 25 10:37:03 2003 +0100 @@ -22,7 +22,7 @@ mult_assoc: "(a * b) * c = a * (b * c)" mult_commute: "a * b = b * a" - left_one [simp]: "1 * a = a" + mult_1 [simp]: "1 * a = a" left_distrib: "(a + b) * c = a * c + b * c" zero_neq_one [simp]: "0 \ 1" @@ -133,10 +133,10 @@ subsection {* Derived rules for multiplication *} -lemma right_one [simp]: "a = a * (1::'a::semiring)" +lemma mult_1_right [simp]: "a * (1::'a::semiring) = a" proof - - have "a = 1 * a" by simp - also have "... = a * 1" by (simp add: mult_commute) + have "a * 1 = 1 * a" by (simp add: mult_commute) + also have "... = a" by simp finally show ?thesis . qed @@ -217,6 +217,12 @@ lemma add_right_mono: "a \ (b::'a::ordered_semiring) ==> 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::'a::ordered_semiring)" + apply (erule add_right_mono [THEN order_trans]) + apply (simp add: add_commute add_left_mono) + done + lemma le_imp_neg_le: assumes "a \ (b::'a::ordered_ring)" shows "-b \ -a" proof - @@ -261,12 +267,14 @@ by (simp add: mult_commute [of _ c] mult_strict_left_mono) lemma mult_left_mono: - "[|a \ b; 0 < c|] ==> c * a \ c * (b::'a::ordered_semiring)" -by (force simp add: mult_strict_left_mono order_le_less) + "[|a \ b; 0 \ c|] ==> c * a \ c * (b::'a::ordered_ring)" + apply (case_tac "c=0", simp) + apply (force simp add: mult_strict_left_mono order_le_less) + done lemma mult_right_mono: - "[|a \ b; 0 < c|] ==> a*c \ b * (c::'a::ordered_semiring)" -by (force simp add: mult_strict_right_mono order_le_less) + "[|a \ b; 0 \ c|] ==> a*c \ b * (c::'a::ordered_ring)" + by (simp add: mult_left_mono mult_commute [of _ c]) lemma mult_strict_left_mono_neg: "[|b < a; c < 0|] ==> c * a < c * (b::'a::ordered_ring)" @@ -281,12 +289,14 @@ done lemma mult_left_mono_neg: - "[|b \ a; c < 0|] ==> c * a \ c * (b::'a::ordered_ring)" -by (force simp add: mult_strict_left_mono_neg order_le_less) + "[|b \ a; c \ 0|] ==> c * a \ c * (b::'a::ordered_ring)" +apply (drule mult_left_mono [of _ _ "-c"]) +apply (simp_all add: minus_mult_left [symmetric]) +done lemma mult_right_mono_neg: - "[|b \ a; c < 0|] ==> a * c \ b * (c::'a::ordered_ring)" -by (force simp add: mult_strict_right_mono_neg order_le_less) + "[|b \ a; c \ 0|] ==> a * c \ b * (c::'a::ordered_ring)" + by (simp add: mult_left_mono_neg mult_commute [of _ c]) text{*Strict monotonicity in both arguments*} lemma mult_strict_mono: @@ -295,6 +305,14 @@ apply (erule mult_strict_left_mono, assumption) done +lemma mult_mono: + "[|a \ b; c \ d; 0 \ b; 0 \ c|] + ==> a * c \ b * (d::'a::ordered_ring)" +apply (erule mult_right_mono [THEN order_trans], assumption) +apply (erule mult_left_mono, assumption) +done + + subsection{*Cancellation Laws for Relationships With a Common Factor*} text{*Cancellation laws for @{term "c*a < c*b"} and @{term "a*c < b*c"},