src/HOL/Arith.ML
 author paulson Thu Mar 28 12:36:50 1996 +0100 (1996-03-28) changeset 1626 12560b3ebf2c parent 1618 372880456b5b child 1655 5be64540f275 permissions -rw-r--r--
Moved even/odd lemmas from ex/Mutil to Arith
 clasohm@1465 ` 1` ```(* Title: HOL/Arith.ML ``` clasohm@923 ` 2` ``` ID: \$Id\$ ``` clasohm@1465 ` 3` ``` Author: Lawrence C Paulson, Cambridge University Computer Laboratory ``` clasohm@923 ` 4` ``` Copyright 1993 University of Cambridge ``` clasohm@923 ` 5` clasohm@923 ` 6` ```Proofs about elementary arithmetic: addition, multiplication, etc. ``` clasohm@923 ` 7` ```Tests definitions and simplifier. ``` clasohm@923 ` 8` ```*) ``` clasohm@923 ` 9` clasohm@923 ` 10` ```open Arith; ``` clasohm@923 ` 11` clasohm@923 ` 12` ```(*** Basic rewrite rules for the arithmetic operators ***) ``` clasohm@923 ` 13` clasohm@923 ` 14` ```val [pred_0, pred_Suc] = nat_recs pred_def; ``` clasohm@923 ` 15` ```val [add_0,add_Suc] = nat_recs add_def; ``` clasohm@923 ` 16` ```val [mult_0,mult_Suc] = nat_recs mult_def; ``` nipkow@1301 ` 17` ```Addsimps [pred_0,pred_Suc,add_0,add_Suc,mult_0,mult_Suc]; ``` nipkow@1301 ` 18` nipkow@1301 ` 19` ```(** pred **) ``` nipkow@1301 ` 20` nipkow@1301 ` 21` ```val prems = goal Arith.thy "n ~= 0 ==> Suc(pred n) = n"; ``` paulson@1552 ` 22` ```by (res_inst_tac [("n","n")] natE 1); ``` paulson@1552 ` 23` ```by (cut_facts_tac prems 1); ``` paulson@1552 ` 24` ```by (ALLGOALS Asm_full_simp_tac); ``` nipkow@1301 ` 25` ```qed "Suc_pred"; ``` nipkow@1301 ` 26` ```Addsimps [Suc_pred]; ``` clasohm@923 ` 27` clasohm@923 ` 28` ```(** Difference **) ``` clasohm@923 ` 29` clasohm@923 ` 30` ```val diff_0 = diff_def RS def_nat_rec_0; ``` clasohm@923 ` 31` clasohm@923 ` 32` ```qed_goalw "diff_0_eq_0" Arith.thy [diff_def, pred_def] ``` clasohm@923 ` 33` ``` "0 - n = 0" ``` clasohm@1264 ` 34` ``` (fn _ => [nat_ind_tac "n" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 35` clasohm@923 ` 36` ```(*Must simplify BEFORE the induction!! (Else we get a critical pair) ``` clasohm@923 ` 37` ``` Suc(m) - Suc(n) rewrites to pred(Suc(m) - n) *) ``` clasohm@923 ` 38` ```qed_goalw "diff_Suc_Suc" Arith.thy [diff_def, pred_def] ``` clasohm@923 ` 39` ``` "Suc(m) - Suc(n) = m - n" ``` clasohm@923 ` 40` ``` (fn _ => ``` clasohm@1264 ` 41` ``` [Simp_tac 1, nat_ind_tac "n" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 42` nipkow@1301 ` 43` ```Addsimps [diff_0, diff_0_eq_0, diff_Suc_Suc]; ``` clasohm@923 ` 44` clasohm@923 ` 45` clasohm@923 ` 46` ```(**** Inductive properties of the operators ****) ``` clasohm@923 ` 47` clasohm@923 ` 48` ```(*** Addition ***) ``` clasohm@923 ` 49` clasohm@923 ` 50` ```qed_goal "add_0_right" Arith.thy "m + 0 = m" ``` clasohm@1264 ` 51` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 52` clasohm@923 ` 53` ```qed_goal "add_Suc_right" Arith.thy "m + Suc(n) = Suc(m+n)" ``` clasohm@1264 ` 54` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 55` clasohm@1264 ` 56` ```Addsimps [add_0_right,add_Suc_right]; ``` clasohm@923 ` 57` clasohm@923 ` 58` ```(*Associative law for addition*) ``` clasohm@923 ` 59` ```qed_goal "add_assoc" Arith.thy "(m + n) + k = m + ((n + k)::nat)" ``` clasohm@1264 ` 60` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 61` clasohm@923 ` 62` ```(*Commutative law for addition*) ``` clasohm@923 ` 63` ```qed_goal "add_commute" Arith.thy "m + n = n + (m::nat)" ``` clasohm@1264 ` 64` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 65` clasohm@923 ` 66` ```qed_goal "add_left_commute" Arith.thy "x+(y+z)=y+((x+z)::nat)" ``` clasohm@923 ` 67` ``` (fn _ => [rtac (add_commute RS trans) 1, rtac (add_assoc RS trans) 1, ``` clasohm@923 ` 68` ``` rtac (add_commute RS arg_cong) 1]); ``` clasohm@923 ` 69` clasohm@923 ` 70` ```(*Addition is an AC-operator*) ``` clasohm@923 ` 71` ```val add_ac = [add_assoc, add_commute, add_left_commute]; ``` clasohm@923 ` 72` clasohm@923 ` 73` ```goal Arith.thy "!!k::nat. (k + m = k + n) = (m=n)"; ``` clasohm@923 ` 74` ```by (nat_ind_tac "k" 1); ``` clasohm@1264 ` 75` ```by (Simp_tac 1); ``` clasohm@1264 ` 76` ```by (Asm_simp_tac 1); ``` clasohm@923 ` 77` ```qed "add_left_cancel"; ``` clasohm@923 ` 78` clasohm@923 ` 79` ```goal Arith.thy "!!k::nat. (m + k = n + k) = (m=n)"; ``` clasohm@923 ` 80` ```by (nat_ind_tac "k" 1); ``` clasohm@1264 ` 81` ```by (Simp_tac 1); ``` clasohm@1264 ` 82` ```by (Asm_simp_tac 1); ``` clasohm@923 ` 83` ```qed "add_right_cancel"; ``` clasohm@923 ` 84` clasohm@923 ` 85` ```goal Arith.thy "!!k::nat. (k + m <= k + n) = (m<=n)"; ``` clasohm@923 ` 86` ```by (nat_ind_tac "k" 1); ``` clasohm@1264 ` 87` ```by (Simp_tac 1); ``` clasohm@1264 ` 88` ```by (Asm_simp_tac 1); ``` clasohm@923 ` 89` ```qed "add_left_cancel_le"; ``` clasohm@923 ` 90` clasohm@923 ` 91` ```goal Arith.thy "!!k::nat. (k + m < k + n) = (m m + pred n = pred(m+n)"; ``` nipkow@1327 ` 107` ```by (nat_ind_tac "m" 1); ``` nipkow@1327 ` 108` ```by (ALLGOALS Asm_simp_tac); ``` nipkow@1327 ` 109` ```qed "add_pred"; ``` nipkow@1327 ` 110` ```Addsimps [add_pred]; ``` nipkow@1327 ` 111` clasohm@923 ` 112` ```(*** Multiplication ***) ``` clasohm@923 ` 113` clasohm@923 ` 114` ```(*right annihilation in product*) ``` clasohm@923 ` 115` ```qed_goal "mult_0_right" Arith.thy "m * 0 = 0" ``` clasohm@1264 ` 116` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 117` clasohm@923 ` 118` ```(*right Sucessor law for multiplication*) ``` clasohm@923 ` 119` ```qed_goal "mult_Suc_right" Arith.thy "m * Suc(n) = m + (m * n)" ``` clasohm@923 ` 120` ``` (fn _ => [nat_ind_tac "m" 1, ``` clasohm@1264 ` 121` ``` ALLGOALS(asm_simp_tac (!simpset addsimps add_ac))]); ``` clasohm@923 ` 122` clasohm@1264 ` 123` ```Addsimps [mult_0_right,mult_Suc_right]; ``` clasohm@923 ` 124` clasohm@923 ` 125` ```(*Commutative law for multiplication*) ``` clasohm@923 ` 126` ```qed_goal "mult_commute" Arith.thy "m * n = n * (m::nat)" ``` clasohm@1264 ` 127` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 128` clasohm@923 ` 129` ```(*addition distributes over multiplication*) ``` clasohm@923 ` 130` ```qed_goal "add_mult_distrib" Arith.thy "(m + n)*k = (m*k) + ((n*k)::nat)" ``` clasohm@923 ` 131` ``` (fn _ => [nat_ind_tac "m" 1, ``` clasohm@1264 ` 132` ``` ALLGOALS(asm_simp_tac (!simpset addsimps add_ac))]); ``` clasohm@923 ` 133` clasohm@923 ` 134` ```qed_goal "add_mult_distrib2" Arith.thy "k*(m + n) = (k*m) + ((k*n)::nat)" ``` clasohm@923 ` 135` ``` (fn _ => [nat_ind_tac "m" 1, ``` clasohm@1264 ` 136` ``` ALLGOALS(asm_simp_tac (!simpset addsimps add_ac))]); ``` clasohm@923 ` 137` clasohm@1264 ` 138` ```Addsimps [add_mult_distrib,add_mult_distrib2]; ``` clasohm@923 ` 139` clasohm@923 ` 140` ```(*Associative law for multiplication*) ``` clasohm@923 ` 141` ```qed_goal "mult_assoc" Arith.thy "(m * n) * k = m * ((n * k)::nat)" ``` clasohm@1264 ` 142` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` clasohm@923 ` 143` clasohm@923 ` 144` ```qed_goal "mult_left_commute" Arith.thy "x*(y*z) = y*((x*z)::nat)" ``` clasohm@923 ` 145` ``` (fn _ => [rtac trans 1, rtac mult_commute 1, rtac trans 1, ``` clasohm@923 ` 146` ``` rtac mult_assoc 1, rtac (mult_commute RS arg_cong) 1]); ``` clasohm@923 ` 147` clasohm@923 ` 148` ```val mult_ac = [mult_assoc,mult_commute,mult_left_commute]; ``` clasohm@923 ` 149` clasohm@923 ` 150` ```(*** Difference ***) ``` clasohm@923 ` 151` clasohm@923 ` 152` ```qed_goal "diff_self_eq_0" Arith.thy "m - m = 0" ``` clasohm@1264 ` 153` ``` (fn _ => [nat_ind_tac "m" 1, ALLGOALS Asm_simp_tac]); ``` nipkow@1496 ` 154` ```Addsimps [diff_self_eq_0]; ``` clasohm@923 ` 155` clasohm@923 ` 156` ```(*Addition is the inverse of subtraction: if n<=m then n+(m-n) = m. *) ``` clasohm@923 ` 157` ```val [prem] = goal Arith.thy "[| ~ m n+(m-n) = (m::nat)"; ``` clasohm@923 ` 158` ```by (rtac (prem RS rev_mp) 1); ``` clasohm@923 ` 159` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@1264 ` 160` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 161` ```qed "add_diff_inverse"; ``` clasohm@923 ` 162` clasohm@923 ` 163` clasohm@923 ` 164` ```(*** Remainder ***) ``` clasohm@923 ` 165` clasohm@923 ` 166` ```goal Arith.thy "m - n < Suc(m)"; ``` clasohm@923 ` 167` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@923 ` 168` ```by (etac less_SucE 3); ``` clasohm@1264 ` 169` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 170` ```qed "diff_less_Suc"; ``` clasohm@923 ` 171` clasohm@923 ` 172` ```goal Arith.thy "!!m::nat. m - n <= m"; ``` clasohm@923 ` 173` ```by (res_inst_tac [("m","m"), ("n","n")] diff_induct 1); ``` clasohm@1264 ` 174` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 175` ```qed "diff_le_self"; ``` clasohm@923 ` 176` clasohm@923 ` 177` ```goal Arith.thy "!!n::nat. (n+m) - n = m"; ``` clasohm@923 ` 178` ```by (nat_ind_tac "n" 1); ``` clasohm@1264 ` 179` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 180` ```qed "diff_add_inverse"; ``` clasohm@923 ` 181` clasohm@923 ` 182` ```goal Arith.thy "!!n::nat. n - (n+m) = 0"; ``` clasohm@923 ` 183` ```by (nat_ind_tac "n" 1); ``` clasohm@1264 ` 184` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 185` ```qed "diff_add_0"; ``` clasohm@923 ` 186` clasohm@923 ` 187` ```(*In ordinary notation: if 0 m - n < m"; ``` clasohm@923 ` 189` ```by (subgoal_tac "0 ~ m m - n < m" 1); ``` clasohm@923 ` 190` ```by (fast_tac HOL_cs 1); ``` clasohm@923 ` 191` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@1264 ` 192` ```by (ALLGOALS(asm_simp_tac(!simpset addsimps [diff_less_Suc]))); ``` nipkow@1398 ` 193` ```qed "diff_less"; ``` clasohm@923 ` 194` clasohm@923 ` 195` ```val wf_less_trans = wf_pred_nat RS wf_trancl RSN (2, def_wfrec RS trans); ``` clasohm@923 ` 196` clasohm@972 ` 197` ```goalw Nat.thy [less_def] "(m,n) : pred_nat^+ = (m m mod n = m"; ``` clasohm@1475 ` 207` ```by (rtac (mod_def1 RS wf_less_trans) 1); ``` paulson@1552 ` 208` ```by (Asm_simp_tac 1); ``` clasohm@923 ` 209` ```qed "mod_less"; ``` clasohm@923 ` 210` clasohm@923 ` 211` ```goal Arith.thy "!!m. [| 0 m mod n = (m-n) mod n"; ``` clasohm@1475 ` 212` ```by (rtac (mod_def1 RS wf_less_trans) 1); ``` paulson@1552 ` 213` ```by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); ``` clasohm@923 ` 214` ```qed "mod_geq"; ``` clasohm@923 ` 215` clasohm@923 ` 216` clasohm@923 ` 217` ```(*** Quotient ***) ``` clasohm@923 ` 218` clasohm@1475 ` 219` ```goal Arith.thy "(%m. m div n) = wfrec (trancl pred_nat) \ ``` clasohm@1475 ` 220` ``` \ (%f j. if j m div n = 0"; ``` clasohm@1475 ` 225` ```by (rtac (div_def1 RS wf_less_trans) 1); ``` paulson@1552 ` 226` ```by (Asm_simp_tac 1); ``` clasohm@923 ` 227` ```qed "div_less"; ``` clasohm@923 ` 228` clasohm@923 ` 229` ```goal Arith.thy "!!M. [| 0 m div n = Suc((m-n) div n)"; ``` clasohm@1475 ` 230` ```by (rtac (div_def1 RS wf_less_trans) 1); ``` paulson@1552 ` 231` ```by (asm_simp_tac (!simpset addsimps [diff_less, cut_apply, less_eq]) 1); ``` clasohm@923 ` 232` ```qed "div_geq"; ``` clasohm@923 ` 233` clasohm@923 ` 234` ```(*Main Result about quotient and remainder.*) ``` clasohm@923 ` 235` ```goal Arith.thy "!!m. 0 (m div n)*n + m mod n = m"; ``` clasohm@923 ` 236` ```by (res_inst_tac [("n","m")] less_induct 1); ``` clasohm@923 ` 237` ```by (rename_tac "k" 1); (*Variable name used in line below*) ``` clasohm@923 ` 238` ```by (case_tac "k m-n = 0"; ``` clasohm@923 ` 248` ```by (rtac (prem RS rev_mp) 1); ``` clasohm@923 ` 249` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@1264 ` 250` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 251` ```qed "less_imp_diff_is_0"; ``` clasohm@923 ` 252` clasohm@923 ` 253` ```val prems = goal Arith.thy "m-n = 0 --> n-m = 0 --> m=n"; ``` clasohm@923 ` 254` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@1264 ` 255` ```by (REPEAT(Simp_tac 1 THEN TRY(atac 1))); ``` nipkow@1485 ` 256` ```qed_spec_mp "diffs0_imp_equal"; ``` clasohm@923 ` 257` clasohm@923 ` 258` ```val [prem] = goal Arith.thy "m 0 Suc(m)-n = Suc(m-n)"; ``` clasohm@923 ` 265` ```by (rtac (prem RS rev_mp) 1); ``` clasohm@923 ` 266` ```by (res_inst_tac [("m","m"),("n","n")] diff_induct 1); ``` clasohm@1264 ` 267` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 268` ```qed "Suc_diff_n"; ``` clasohm@923 ` 269` nipkow@1398 ` 270` ```goal Arith.thy "Suc(m)-n = (if m (!n. P(Suc(n))--> P(n)) --> P(k-i)"; ``` clasohm@923 ` 276` ```by (res_inst_tac [("m","k"),("n","i")] diff_induct 1); ``` clasohm@1264 ` 277` ```by (ALLGOALS (strip_tac THEN' Simp_tac THEN' TRY o fast_tac HOL_cs)); ``` clasohm@923 ` 278` ```qed "zero_induct_lemma"; ``` clasohm@923 ` 279` clasohm@923 ` 280` ```val prems = goal Arith.thy "[| P(k); !!n. P(Suc(n)) ==> P(n) |] ==> P(0)"; ``` clasohm@923 ` 281` ```by (rtac (diff_self_eq_0 RS subst) 1); ``` clasohm@923 ` 282` ```by (rtac (zero_induct_lemma RS mp RS mp) 1); ``` clasohm@923 ` 283` ```by (REPEAT (ares_tac ([impI,allI]@prems) 1)); ``` clasohm@923 ` 284` ```qed "zero_induct"; ``` clasohm@923 ` 285` clasohm@923 ` 286` ```(*13 July 1992: loaded in 105.7s*) ``` clasohm@923 ` 287` paulson@1618 ` 288` paulson@1618 ` 289` ```(*** Further facts about mod (mainly for mutilated checkerboard ***) ``` paulson@1618 ` 290` paulson@1618 ` 291` ```goal Arith.thy ``` paulson@1618 ` 292` ``` "!!m n. 0 \ ``` paulson@1618 ` 293` ```\ Suc(m) mod n = (if Suc(m mod n) = n then 0 else Suc(m mod n))"; ``` paulson@1618 ` 294` ```by (res_inst_tac [("n","m")] less_induct 1); ``` paulson@1618 ` 295` ```by (excluded_middle_tac "Suc(na) m mod n < n"; ``` paulson@1618 ` 309` ```by (res_inst_tac [("n","m")] less_induct 1); ``` paulson@1618 ` 310` ```by (excluded_middle_tac "na k mod 2 = b | k mod 2 = (if b=1 then 0 else 1)"; ``` paulson@1626 ` 323` ```by (subgoal_tac "k mod 2 < 2" 1); ``` paulson@1626 ` 324` ```by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); ``` paulson@1626 ` 325` ```by (asm_simp_tac (!simpset setloop split_tac [expand_if]) 1); ``` paulson@1626 ` 326` ```by (fast_tac less_cs 1); ``` paulson@1626 ` 327` ```qed "mod2_cases"; ``` paulson@1626 ` 328` paulson@1626 ` 329` ```goal thy "Suc(Suc(m)) mod 2 = m mod 2"; ``` paulson@1626 ` 330` ```by (subgoal_tac "m mod 2 < 2" 1); ``` paulson@1626 ` 331` ```by (asm_simp_tac (!simpset addsimps [mod_less_divisor]) 2); ``` paulson@1626 ` 332` ```by (safe_tac less_cs); ``` paulson@1626 ` 333` ```by (ALLGOALS (asm_simp_tac (!simpset addsimps [mod_Suc]))); ``` paulson@1626 ` 334` ```qed "mod2_Suc_Suc"; ``` paulson@1626 ` 335` ```Addsimps [mod2_Suc_Suc]; ``` paulson@1626 ` 336` paulson@1626 ` 337` ```goal thy "(m+m) mod 2 = 0"; ``` paulson@1626 ` 338` ```by (nat_ind_tac "m" 1); ``` paulson@1626 ` 339` ```by (simp_tac (!simpset addsimps [mod_less]) 1); ``` paulson@1626 ` 340` ```by (asm_simp_tac (!simpset addsimps [mod2_Suc_Suc, add_Suc_right]) 1); ``` paulson@1626 ` 341` ```qed "mod2_add_self"; ``` paulson@1626 ` 342` ```Addsimps [mod2_add_self]; ``` paulson@1626 ` 343` paulson@1626 ` 344` clasohm@923 ` 345` ```(**** Additional theorems about "less than" ****) ``` clasohm@923 ` 346` clasohm@923 ` 347` ```goal Arith.thy "!!m. m (? k. n=Suc(m+k))"; ``` clasohm@923 ` 348` ```by (nat_ind_tac "n" 1); ``` clasohm@1264 ` 349` ```by (ALLGOALS(Simp_tac)); ``` clasohm@923 ` 350` ```by (REPEAT_FIRST (ares_tac [conjI, impI])); ``` clasohm@923 ` 351` ```by (res_inst_tac [("x","0")] exI 2); ``` clasohm@1264 ` 352` ```by (Simp_tac 2); ``` clasohm@923 ` 353` ```by (safe_tac HOL_cs); ``` clasohm@923 ` 354` ```by (res_inst_tac [("x","Suc(k)")] exI 1); ``` clasohm@1264 ` 355` ```by (Simp_tac 1); ``` nipkow@1485 ` 356` ```qed_spec_mp "less_eq_Suc_add"; ``` clasohm@923 ` 357` clasohm@923 ` 358` ```goal Arith.thy "n <= ((m + n)::nat)"; ``` clasohm@923 ` 359` ```by (nat_ind_tac "m" 1); ``` clasohm@1264 ` 360` ```by (ALLGOALS Simp_tac); ``` clasohm@923 ` 361` ```by (etac le_trans 1); ``` clasohm@923 ` 362` ```by (rtac (lessI RS less_imp_le) 1); ``` clasohm@923 ` 363` ```qed "le_add2"; ``` clasohm@923 ` 364` clasohm@923 ` 365` ```goal Arith.thy "n <= ((n + m)::nat)"; ``` clasohm@1264 ` 366` ```by (simp_tac (!simpset addsimps add_ac) 1); ``` clasohm@923 ` 367` ```by (rtac le_add2 1); ``` clasohm@923 ` 368` ```qed "le_add1"; ``` clasohm@923 ` 369` clasohm@923 ` 370` ```bind_thm ("less_add_Suc1", (lessI RS (le_add1 RS le_less_trans))); ``` clasohm@923 ` 371` ```bind_thm ("less_add_Suc2", (lessI RS (le_add2 RS le_less_trans))); ``` clasohm@923 ` 372` clasohm@923 ` 373` ```(*"i <= j ==> i <= j+m"*) ``` clasohm@923 ` 374` ```bind_thm ("trans_le_add1", le_add1 RSN (2,le_trans)); ``` clasohm@923 ` 375` clasohm@923 ` 376` ```(*"i <= j ==> i <= m+j"*) ``` clasohm@923 ` 377` ```bind_thm ("trans_le_add2", le_add2 RSN (2,le_trans)); ``` clasohm@923 ` 378` clasohm@923 ` 379` ```(*"i < j ==> i < j+m"*) ``` clasohm@923 ` 380` ```bind_thm ("trans_less_add1", le_add1 RSN (2,less_le_trans)); ``` clasohm@923 ` 381` clasohm@923 ` 382` ```(*"i < j ==> i < m+j"*) ``` clasohm@923 ` 383` ```bind_thm ("trans_less_add2", le_add2 RSN (2,less_le_trans)); ``` clasohm@923 ` 384` nipkow@1152 ` 385` ```goal Arith.thy "!!i. i+j < (k::nat) ==> i m <= n+k"; ``` paulson@1552 ` 393` ```by (etac le_trans 1); ``` paulson@1552 ` 394` ```by (rtac le_add1 1); ``` clasohm@923 ` 395` ```qed "le_imp_add_le"; ``` clasohm@923 ` 396` clasohm@923 ` 397` ```goal Arith.thy "!!k::nat. m < n ==> m < n+k"; ``` paulson@1552 ` 398` ```by (etac less_le_trans 1); ``` paulson@1552 ` 399` ```by (rtac le_add1 1); ``` clasohm@923 ` 400` ```qed "less_imp_add_less"; ``` clasohm@923 ` 401` clasohm@923 ` 402` ```goal Arith.thy "m+k<=n --> m<=(n::nat)"; ``` clasohm@923 ` 403` ```by (nat_ind_tac "k" 1); ``` clasohm@1264 ` 404` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 405` ```by (fast_tac (HOL_cs addDs [Suc_leD]) 1); ``` nipkow@1485 ` 406` ```qed_spec_mp "add_leD1"; ``` clasohm@923 ` 407` clasohm@923 ` 408` ```goal Arith.thy "!!k l::nat. [| k m i + k < j + k"; ``` clasohm@923 ` 424` ```by (nat_ind_tac "k" 1); ``` clasohm@1264 ` 425` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 426` ```qed "add_less_mono1"; ``` clasohm@923 ` 427` clasohm@923 ` 428` ```(*strict, in both arguments*) ``` clasohm@923 ` 429` ```goal Arith.thy "!!i j k::nat. [|i < j; k < l|] ==> i + k < j + l"; ``` clasohm@923 ` 430` ```by (rtac (add_less_mono1 RS less_trans) 1); ``` lcp@1198 ` 431` ```by (REPEAT (assume_tac 1)); ``` clasohm@923 ` 432` ```by (nat_ind_tac "j" 1); ``` clasohm@1264 ` 433` ```by (ALLGOALS Asm_simp_tac); ``` clasohm@923 ` 434` ```qed "add_less_mono"; ``` clasohm@923 ` 435` clasohm@923 ` 436` ```(*A [clumsy] way of lifting < monotonicity to <= monotonicity *) ``` clasohm@923 ` 437` ```val [lt_mono,le] = goal Arith.thy ``` clasohm@1465 ` 438` ``` "[| !!i j::nat. i f(i) < f(j); \ ``` clasohm@1465 ` 439` ```\ i <= j \ ``` clasohm@923 ` 440` ```\ |] ==> f(i) <= (f(j)::nat)"; ``` clasohm@923 ` 441` ```by (cut_facts_tac [le] 1); ``` clasohm@1264 ` 442` ```by (asm_full_simp_tac (!simpset addsimps [le_eq_less_or_eq]) 1); ``` clasohm@923 ` 443` ```by (fast_tac (HOL_cs addSIs [lt_mono]) 1); ``` clasohm@923 ` 444` ```qed "less_mono_imp_le_mono"; ``` clasohm@923 ` 445` clasohm@923 ` 446` ```(*non-strict, in 1st argument*) ``` clasohm@923 ` 447` ```goal Arith.thy "!!i j k::nat. i<=j ==> i + k <= j + k"; ``` clasohm@923 ` 448` ```by (res_inst_tac [("f", "%j.j+k")] less_mono_imp_le_mono 1); ``` paulson@1552 ` 449` ```by (etac add_less_mono1 1); ``` clasohm@923 ` 450` ```by (assume_tac 1); ``` clasohm@923 ` 451` ```qed "add_le_mono1"; ``` clasohm@923 ` 452` clasohm@923 ` 453` ```(*non-strict, in both arguments*) ``` clasohm@923 ` 454` ```goal Arith.thy "!!k l::nat. [|i<=j; k<=l |] ==> i + k <= j + l"; ``` clasohm@923 ` 455` ```by (etac (add_le_mono1 RS le_trans) 1); ``` clasohm@1264 ` 456` ```by (simp_tac (!simpset addsimps [add_commute]) 1); ``` clasohm@923 ` 457` ```(*j moves to the end because it is free while k, l are bound*) ``` paulson@1552 ` 458` ```by (etac add_le_mono1 1); ``` clasohm@923 ` 459` ```qed "add_le_mono"; ```