diff -r ccaadfcf6941 -r 8a9228872fbd src/HOL/Fact.thy --- a/src/HOL/Fact.thy Thu Jul 09 17:34:59 2009 +0200 +++ b/src/HOL/Fact.thy Fri Jul 10 10:45:30 2009 -0400 @@ -2,25 +2,266 @@ Author : Jacques D. Fleuriot Copyright : 1998 University of Cambridge Conversion to Isar and new proofs by Lawrence C Paulson, 2004 + The integer version of factorial and other additions by Jeremy Avigad. *) header{*Factorial Function*} theory Fact -imports Main +imports NatTransfer begin -consts fact :: "nat => nat" -primrec - fact_0: "fact 0 = 1" - fact_Suc: "fact (Suc n) = (Suc n) * fact n" +class fact = + +fixes + fact :: "'a \ 'a" + +instantiation nat :: fact + +begin + +fun + fact_nat :: "nat \ nat" +where + fact_0_nat: "fact_nat 0 = Suc 0" +| fact_Suc_nat: "fact_nat (Suc x) = Suc x * fact x" + +instance proof qed + +end + +(* definitions for the integers *) + +instantiation int :: fact + +begin + +definition + fact_int :: "int \ int" +where + "fact_int x = (if x >= 0 then int (fact (nat x)) else 0)" + +instance proof qed + +end + + +subsection {* Set up Transfer *} + +lemma transfer_nat_int_factorial: + "(x::int) >= 0 \ fact (nat x) = nat (fact x)" + unfolding fact_int_def + by auto + + +lemma transfer_nat_int_factorial_closure: + "x >= (0::int) \ fact x >= 0" + by (auto simp add: fact_int_def) + +declare TransferMorphism_nat_int[transfer add return: + transfer_nat_int_factorial transfer_nat_int_factorial_closure] + +lemma transfer_int_nat_factorial: + "fact (int x) = int (fact x)" + unfolding fact_int_def by auto + +lemma transfer_int_nat_factorial_closure: + "is_nat x \ fact x >= 0" + by (auto simp add: fact_int_def) + +declare TransferMorphism_int_nat[transfer add return: + transfer_int_nat_factorial transfer_int_nat_factorial_closure] -lemma fact_gt_zero [simp]: "0 < fact n" -by (induct n) auto +subsection {* Factorial *} + +lemma fact_0_int [simp]: "fact (0::int) = 1" + by (simp add: fact_int_def) + +lemma fact_1_nat [simp]: "fact (1::nat) = 1" + by simp + +lemma fact_Suc_0_nat [simp]: "fact (Suc 0) = Suc 0" + by simp + +lemma fact_1_int [simp]: "fact (1::int) = 1" + by (simp add: fact_int_def) + +lemma fact_plus_one_nat: "fact ((n::nat) + 1) = (n + 1) * fact n" + by simp + +lemma fact_plus_one_int: + assumes "n >= 0" + shows "fact ((n::int) + 1) = (n + 1) * fact n" + + using prems unfolding fact_int_def + by (simp add: nat_add_distrib algebra_simps int_mult) + +lemma fact_reduce_nat: "(n::nat) > 0 \ fact n = n * fact (n - 1)" + apply (subgoal_tac "n = Suc (n - 1)") + apply (erule ssubst) + apply (subst fact_Suc_nat) + apply simp_all +done + +lemma fact_reduce_int: "(n::int) > 0 \ fact n = n * fact (n - 1)" + apply (subgoal_tac "n = (n - 1) + 1") + apply (erule ssubst) + apply (subst fact_plus_one_int) + apply simp_all +done + +lemma fact_nonzero_nat [simp]: "fact (n::nat) \ 0" + apply (induct n) + apply (auto simp add: fact_plus_one_nat) +done + +lemma fact_nonzero_int [simp]: "n >= 0 \ fact (n::int) ~= 0" + by (simp add: fact_int_def) + +lemma fact_gt_zero_nat [simp]: "fact (n :: nat) > 0" + by (insert fact_nonzero_nat [of n], arith) + +lemma fact_gt_zero_int [simp]: "n >= 0 \ fact (n :: int) > 0" + by (auto simp add: fact_int_def) + +lemma fact_ge_one_nat [simp]: "fact (n :: nat) >= 1" + by (insert fact_nonzero_nat [of n], arith) + +lemma fact_ge_Suc_0_nat [simp]: "fact (n :: nat) >= Suc 0" + by (insert fact_nonzero_nat [of n], arith) + +lemma fact_ge_one_int [simp]: "n >= 0 \ fact (n :: int) >= 1" + apply (auto simp add: fact_int_def) + apply (subgoal_tac "1 = int 1") + apply (erule ssubst) + apply (subst zle_int) + apply auto +done + +lemma dvd_fact_nat [rule_format]: "1 <= m \ m <= n \ m dvd fact (n::nat)" + apply (induct n) + apply force + apply (auto simp only: fact_Suc_nat) + apply (subgoal_tac "m = Suc n") + apply (erule ssubst) + apply (rule dvd_triv_left) + apply auto +done + +lemma dvd_fact_int [rule_format]: "1 <= m \ m <= n \ m dvd fact (n::int)" + apply (case_tac "1 <= n") + apply (induct n rule: int_ge_induct) + apply (auto simp add: fact_plus_one_int) + apply (subgoal_tac "m = i + 1") + apply auto +done + +lemma interval_plus_one_nat: "(i::nat) <= j + 1 \ + {i..j+1} = {i..j} Un {j+1}" + by auto + +lemma interval_Suc: "i <= Suc j \ {i..Suc j} = {i..j} Un {Suc j}" + by auto + +lemma interval_plus_one_int: "(i::int) <= j + 1 \ {i..j+1} = {i..j} Un {j+1}" + by auto -lemma fact_not_eq_zero [simp]: "fact n \ 0" -by simp +lemma fact_altdef_nat: "fact (n::nat) = (PROD i:{1..n}. i)" + apply (induct n) + apply force + apply (subst fact_Suc_nat) + apply (subst interval_Suc) + apply auto +done + +lemma fact_altdef_int: "n >= 0 \ fact (n::int) = (PROD i:{1..n}. i)" + apply (induct n rule: int_ge_induct) + apply force + apply (subst fact_plus_one_int, assumption) + apply (subst interval_plus_one_int) + apply auto +done + +lemma fact_mono_nat: "(m::nat) \ n \ fact m \ fact n" +apply (drule le_imp_less_or_eq) +apply (auto dest!: less_imp_Suc_add) +apply (induct_tac k, auto) +done + +lemma fact_neg_int [simp]: "m < (0::int) \ fact m = 0" + unfolding fact_int_def by auto + +lemma fact_ge_zero_int [simp]: "fact m >= (0::int)" + apply (case_tac "m >= 0") + apply auto + apply (frule fact_gt_zero_int) + apply arith +done + +lemma fact_mono_int_aux [rule_format]: "k >= (0::int) \ + fact (m + k) >= fact m" + apply (case_tac "m < 0") + apply auto + apply (induct k rule: int_ge_induct) + apply auto + apply (subst add_assoc [symmetric]) + apply (subst fact_plus_one_int) + apply auto + apply (erule order_trans) + apply (subst mult_le_cancel_right1) + apply (subgoal_tac "fact (m + i) >= 0") + apply arith + apply auto +done + +lemma fact_mono_int: "(m::int) <= n \ fact m <= fact n" + apply (insert fact_mono_int_aux [of "n - m" "m"]) + apply auto +done + +text{*Note that @{term "fact 0 = fact 1"}*} +lemma fact_less_mono_nat: "[| (0::nat) < m; m < n |] ==> fact m < fact n" +apply (drule_tac m = m in less_imp_Suc_add, auto) +apply (induct_tac k, auto) +done + +lemma fact_less_mono_int_aux: "k >= 0 \ (0::int) < m \ + fact m < fact ((m + 1) + k)" + apply (induct k rule: int_ge_induct) + apply (simp add: fact_plus_one_int) + apply (subst mult_less_cancel_right1) + apply (insert fact_gt_zero_int [of m], arith) + apply (subst (2) fact_reduce_int) + apply (auto simp add: add_ac) + apply (erule order_less_le_trans) + apply (subst mult_le_cancel_right1) + apply auto + apply (subgoal_tac "fact (i + (1 + m)) >= 0") + apply force + apply (rule fact_ge_zero_int) +done + +lemma fact_less_mono_int: "(0::int) < m \ m < n \ fact m < fact n" + apply (insert fact_less_mono_int_aux [of "n - (m + 1)" "m"]) + apply auto +done + +lemma fact_num_eq_if_nat: "fact (m::nat) = + (if m=0 then 1 else m * fact (m - 1))" +by (cases m) auto + +lemma fact_add_num_eq_if_nat: + "fact ((m::nat) + n) = (if m + n = 0 then 1 else (m + n) * fact (m + n - 1))" +by (cases "m + n") auto + +lemma fact_add_num_eq_if2_nat: + "fact ((m::nat) + n) = + (if m = 0 then fact n else (m + n) * fact ((m - 1) + n))" +by (cases m) auto + + +subsection {* fact and of_nat *} lemma of_nat_fact_not_zero [simp]: "of_nat (fact n) \ (0::'a::semiring_char_0)" by auto @@ -33,46 +274,10 @@ lemma of_nat_fact_ge_zero [simp]: "(0::'a::ordered_semidom) \ of_nat(fact n)" by simp -lemma fact_ge_one [simp]: "1 \ fact n" -by (induct n) auto - -lemma fact_mono: "m \ n ==> fact m \ fact n" -apply (drule le_imp_less_or_eq) -apply (auto dest!: less_imp_Suc_add) -apply (induct_tac k, auto) -done - -text{*Note that @{term "fact 0 = fact 1"}*} -lemma fact_less_mono: "[| 0 < m; m < n |] ==> fact m < fact n" -apply (drule_tac m = m in less_imp_Suc_add, auto) -apply (induct_tac k, auto) -done - lemma inv_of_nat_fact_gt_zero [simp]: "(0::'a::ordered_field) < inverse (of_nat (fact n))" by (auto simp add: positive_imp_inverse_positive) lemma inv_of_nat_fact_ge_zero [simp]: "(0::'a::ordered_field) \ inverse (of_nat (fact n))" by (auto intro: order_less_imp_le) -lemma fact_diff_Suc [rule_format]: - "n < Suc m ==> fact (Suc m - n) = (Suc m - n) * fact (m - n)" -apply (induct n arbitrary: m) -apply auto -apply (drule_tac x = "m - Suc 0" in meta_spec, auto) -done - -lemma fact_num0: "fact 0 = 1" -by auto - -lemma fact_num_eq_if: "fact m = (if m=0 then 1 else m * fact (m - 1))" -by (cases m) auto - -lemma fact_add_num_eq_if: - "fact (m + n) = (if m + n = 0 then 1 else (m + n) * fact (m + n - 1))" -by (cases "m + n") auto - -lemma fact_add_num_eq_if2: - "fact (m + n) = (if m = 0 then fact n else (m + n) * fact ((m - 1) + n))" -by (cases m) auto - end