Up to index of Isabelle/HOL/HOL-Complex/NumberTheory
theory IntFactorization = Factorization + NatIntLib:(* Title: IntFactorization.thy Author: David Gray *) header {* Unique factorization for integers *} theory IntFactorization = Factorization + NatIntLib:; (********************************************************************) (* the following 5 lemmas set up the zprime, prime set equivalence *) (* but gr_1_prop is also used for other things in this file... *) (* should move all these to IntPrimes (or Int2, though IntPrimes *) (* would be better)? *) (********************************************************************) lemma gr_1_prop: "(1 < p) = (1 < nat p)"; by (auto simp add: zless_nat_eq_int_zless); lemma int_nat_dvd_prop: "(m dvd p) = (int m dvd int p)"; apply (auto simp add: dvd_def); apply (rule_tac x = "int k" in exI); apply (auto simp add: zmult_int); apply (rule_tac x = "nat k" in exI); proof-; fix k; assume "int p = int m * k"; then have "nat (int p) = nat(int m * k)"; by (auto); then have "p = nat(int m * k)"; by (auto); also have "... = nat(int m) * nat k"; apply (insert nat_mult_distrib [of "int m" k]); apply (auto); done; finally have "p = nat (int m) * nat k".; thus "p = m * nat k"; by auto; qed; lemma nat_int_dvd_prop: "[| 0 < m; m dvd p |] ==> (nat m dvd nat p)"; by (auto simp add: int_nat_dvd_prop); lemma nat_prime_prop: "(p: zprime) = ((nat p): prime)"; proof; assume "p : zprime"; then have p:"0 <= p" by (auto simp add: zprime_def); from prems show "(nat p):prime"; apply (auto simp add: prems zprime_def prime_def gr_1_prop); apply (drule_tac x = "int m" in allE, auto); proof-; fix m; assume "m dvd nat p" and "~ int m dvd p"; then have "(int m) dvd int (nat p)"; by (insert int_nat_dvd_prop [of m "nat p"] prems, auto); also have "int (nat p) = p"; by (auto simp add: p); finally have "int m dvd p".; with prems have "False"; by auto; thus "m = Suc 0"; by auto; qed; next; assume "nat p : prime"; thus "p : zprime"; apply (auto simp add: prime_def zprime_def gr_1_prop); apply (drule_tac x = "nat m" in allE); apply (auto); proof-; fix m; assume "Suc 0 < nat p" and "0 <= m" and "m dvd p" and "~ nat m dvd nat p"; then have p: "1 < p"; by (auto simp add: gr_1_prop); from prems have "~(int (nat m) dvd int (nat p))"; by (auto simp add: int_nat_dvd_prop); also have "int (nat m) = m" by (auto simp add: prems); also have "int (nat p) = p" by (insert p, auto); finally have "~(m dvd p)" .; with prems have "False" by auto; thus "m = 1"; by auto; next; fix m; assume "nat m = Suc 0" and p:"0 <= m"; then have "int (nat m) = int (Suc 0)" by auto; also have "int (nat m) = m" by (auto simp add: p); also have "int (Suc 0) = 1" by auto; finally show "m = 1" .; next; fix m; assume "Suc 0 < nat p" and p1:"0 <= m" and "m ~= p" and "nat m = nat p"; then have p2: "1 < p"; by (auto simp add: gr_1_prop); from prems have "int (nat m) = int (nat p)"; by auto; also have "int (nat m) = m" by (auto simp add: p1); also have "int (nat p) = p" by (insert p2, auto); finally have "m = p" .; with prems have "False" by auto; thus "m = 1" by auto; qed; qed; lemma int_prime_prop: "(int p : zprime) = (p : prime)"; by (auto simp add: nat_prime_prop); (****************************) (* Now for the real stuff!! *) (****************************) consts intl :: "nat list => int list" natl :: "int list => nat list" zprimel :: "int list => bool" znondec :: "int list => bool" zprod :: "int list => int"; primrec "natl [] = []" "natl (x # xs) = (nat x) # (natl xs)"; primrec "intl [] = []" "intl (x # xs) = (int x) # (intl xs)"; defs zprimel_def: "zprimel xs == set xs ⊆ zprime"; primrec "znondec [] = True" "znondec (x # xs) = (case xs of [] => True | y # ys => x <= y ∧ znondec xs)"; primrec "zprod [] = 1" "zprod (x # xs) = x * zprod xs"; subsection {* Properties about intl and natl *} lemma intl_natl_prime [rule_format]: "zprimel x --> intl (natl x) = x"; by (induct_tac x, auto simp add: zprimel_def zprime_def); lemma intl_natl_prop [rule_format]: "x = y --> intl x = intl y"; by (induct x, auto); subsection {* Properties about zprimel *} lemma zprimel_distrib1: "zprimel (h # t) ==> (h : zprime)"; by (auto simp add: zprime_def zprimel_def); lemma zprimel_distrib2: "zprimel (h # t) ==> zprimel t"; by (auto simp add: zprime_def zprimel_def); lemma aux [rule_format]: "zprimel (a # list) --> zprimel y --> nat a # natl list = natl y --> a # list ~= y --> natl list = natl y"; apply (induct y, force); apply (clarify, auto); proof-; fix aa and lista; assume "zprimel (a # list)" and "zprimel (aa # lista)" and "nat a = nat aa"; then have "0 <= a" and "0 <= aa"; by (auto simp add: zprimel_def zprime_def); thus "a = aa" by (auto simp add: nat_pos_prop prems); next; fix aa and lista; assume "zprimel (a # list)" and "zprimel (aa # lista)" and "natl list = natl lista"; then have "intl (natl list) = intl (natl lista)"; by (rule_tac x = "natl list" in intl_natl_prop, auto); also have "intl (natl list) = list"; proof-; from prems have "zprimel (a # list)"; by auto; then have "zprimel list" by (rule zprimel_distrib2); thus "intl (natl list) = list" by (rule intl_natl_prime); qed; also have "intl (natl lista) = lista"; proof-; from prems have "zprimel (aa # lista)"; by auto; then have "zprimel lista" by (rule zprimel_distrib2); thus "intl (natl lista) = lista" by (rule intl_natl_prime); qed; finally show "list = lista" .; qed; lemma zprimel_natl_prop: "[| zprimel x; zprimel y; natl x = natl y |] ==> x = y"; proof-; assume "zprimel x" and "zprimel y" and "natl x = natl y"; have "zprimel x & zprimel y & natl x = natl y --> x = y"; apply (induct x, induct y, auto); apply (simp add: zprimel_def); apply (rule aux, auto); done; with prems show "x = y" by auto; qed; lemma zprimel_conversion: "primel l = zprimel (intl l)"; apply (induct l); apply (auto simp add: primel_def zprimel_def int_prime_prop); done; subsection {* Properties about zprod *} lemma zprod_pos: "0 <= zprod(intl l)"; apply (induct l, auto); proof-; fix a and list; assume "0 <= zprod (intl list)"; moreover have "0 <= int a" by auto; ultimately show "0 <= int a * zprod (intl list)"; by (auto simp add: zero_le_mult_iff); qed; lemma zprod_conversion: "prod l = nat (zprod(intl l))"; apply (induct l); apply (auto); proof-; fix a and list; have "a * nat (zprod (intl list)) = nat (int a) * nat (zprod (intl list))"; by (auto); also have "... = nat (int a * zprod (intl list))"; by (auto simp add: nat_mult_distrib); finally show "a * nat (zprod (intl list)) = nat (int a * zprod (intl list))".; qed; lemma zprodl_zprimel_pos [rule_format]: "zprimel pl --> 0 <= zprod (pl)"; apply (induct pl); apply (auto simp add: zprimel_def zprime_def); apply (auto simp add: zero_le_mult_iff); done; lemma zprodl_zprimel_gr_0 [rule_format]: "zprimel pl --> 0 < zprod (pl)"; apply (induct pl); apply (auto simp add: zprimel_def zprime_def); apply (auto simp add: zero_less_mult_iff); done; subsection {* Properties about znondec *} lemma znondec_conversion: "nondec l = znondec (intl l)"; apply (induct l, auto); apply (case_tac list, auto simp add: neq_Nil_conv); apply (case_tac list, auto simp add: neq_Nil_conv); apply (case_tac list, auto simp add: neq_Nil_conv); apply (case_tac list, auto simp add: neq_Nil_conv); done; lemma znondec_distrib [rule_format]: "znondec(a # list) --> znondec(list)"; by (induct list, auto); subsection {* Uniqueness *} lemma temp: "(1::int) < p ==> ~(p dvd 1)"; apply (auto); proof-; assume "1 < p" and "p dvd 1"; moreover from prems have "0 < p" by auto; ultimately have "nat p dvd nat 1"; by (rule_tac m = p in nat_int_dvd_prop, auto); with dvd_1_iff_1 have "nat p = nat 1" by auto; then have "int (nat p) = int (nat 1)" by auto; with prems show "False" by (auto); qed; lemma zprime_zdvd_zmult_list [rule_format]: "p : zprime ==> (p dvd zprod xs) --> (EX m. m : set xs & p dvd m)"; apply (induct xs); apply (simp add: zprime_def);defer; apply (clarsimp); apply (drule_tac p = p and m = a in zprime_zdvd_zmult_better); apply (force, force); proof (clarify); assume "1 < p" and "p dvd 1"; moreover from prems have "0 < p" by auto; ultimately have "nat p dvd nat 1"; by (rule_tac m = p in nat_int_dvd_prop, auto); with dvd_1_iff_1 have "nat p = nat 1" by auto; then have "int (nat p) = int (nat 1)" by auto; with prems show "False" by (auto); qed; lemma zprimes_eq: "[| p : zprime; q : zprime; p dvd q |] ==> p = q"; apply (auto simp add: zprime_def); apply (drule_tac x = q in allE, auto); apply (drule_tac x = p in allE, auto); done; lemma zprime_zdvd_eq: "[| zprimel (x # xs); zprimel ys; m : set ys; x dvd m |] ==> x = m"; apply (rule zprimes_eq); apply (auto simp add: zprimel_distrib1); apply (auto simp add: zprimel_def); done; lemma zfactor_unique: "[| zprimel (intl x); zprimel (intl y); znondec (intl x); znondec (intl y); zprod (intl x) = zprod (intl y) |] ==> x = y"; proof-; assume "zprimel (intl x)" and "zprimel (intl y)" and "znondec (intl x)" and "znondec (intl y)" and "zprod (intl x) = zprod (intl y)"; then have "nat (zprod (intl y)) = nat (zprod (intl x))" by auto; then have "primel x & primel y & prod x = prod y"; by (auto simp add: zprimel_conversion zprod_conversion); with factor_unique have "x <~~> y" by auto; moreover from prems have "nondec x" and "nondec y" by (auto simp add: znondec_conversion); moreover note perm_nondec_unique; ultimately show "x = y" by auto; qed; subsection {* Unique Factorization into Prime Integers *} lemma aux1: "1 < n ==> EX! l. zprimel (intl l) & znondec (intl l) & zprod (intl l) = n"; proof (auto); assume "1 < n"; then have "Suc 0 < nat n" by (auto simp add: gr_1_prop); with unique_prime_factorization have "EX! l. primel l & nondec l & prod l = nat n"; by (auto); then have "EX l. primel l & nondec l & prod l = nat n" by auto; then show "EX l. zprimel (intl l) & znondec (intl l) & zprod (intl l) = n"; apply (auto simp add: zprimel_conversion zprod_conversion znondec_conversion); apply (rule_tac x = l in exI, auto); apply (insert prems, rule nat_pos_prop, auto simp add: zprod_pos); done; next; fix l and y; assume "zprimel (intl l)" and "zprimel (intl y)" and "znondec (intl l)" and "znondec (intl y)" and "zprod (intl y) = zprod (intl l)"; with zfactor_unique show "l = y"; by auto; qed; theorem unique_zprime_factorization: "1 < n ==> EX! l. zprimel l & znondec l & zprod l = n"; proof-; assume "1 < n"; with aux1 have "EX! l. zprimel (intl l) & znondec (intl l) & zprod (intl l) = n"; by auto; then show "EX! l. zprimel l & znondec l & zprod l = n"; apply (auto); apply (rule_tac x = la and y = y in zprimel_natl_prop); apply (auto); apply (rule_tac x = "natl la" in zfactor_unique); proof-; fix la; assume "zprimel la"; with intl_natl_prime have "intl (natl la) = la" by auto; then show "zprimel (intl (natl la))" by auto; next; fix y; assume "zprimel y"; with intl_natl_prime have "intl (natl y) = y" by auto; then show "zprimel (intl (natl y))" by auto; next; fix la; assume "zprimel la" and "znondec la"; with intl_natl_prime have "intl (natl la) = la" by auto; then show "znondec (intl (natl la))" by auto; next; fix y; assume "zprimel y" and "znondec y"; with intl_natl_prime have "intl (natl y) = y" by auto; then show "znondec (intl (natl y))" by auto; next; fix l and la and y; assume "zprimel la" and "zprimel y"; assume "zprod la = zprod (intl l)" and "zprod y = zprod (intl l)"; then have "zprod la = zprod y" by auto; also have "la = intl (natl la)"; by (auto simp add: prems intl_natl_prime); also have "y = intl (natl y)"; by (auto simp add: prems intl_natl_prime); finally show "zprod (intl (natl la)) = zprod (intl (natl y))".; qed; qed; end;
lemma gr_1_prop:
(1 < p) = (1 < nat p)
lemma int_nat_dvd_prop:
(m dvd p) = (int m dvd int p)
lemma nat_int_dvd_prop:
[| 0 < m; m dvd p |] ==> nat m dvd nat p
lemma nat_prime_prop:
(p ∈ zprime) = (nat p ∈ prime)
lemma int_prime_prop:
(int p ∈ zprime) = (p ∈ prime)
lemma intl_natl_prime:
zprimel x ==> intl (natl x) = x
lemma intl_natl_prop:
x = y ==> intl x = intl y
lemma zprimel_distrib1:
zprimel (h # t) ==> h ∈ zprime
lemma zprimel_distrib2:
zprimel (h # t) ==> zprimel t
lemma aux:
[| zprimel (a # list); zprimel y; nat a # natl list = natl y; a # list ≠ y |] ==> natl list = natl y
lemma zprimel_natl_prop:
[| zprimel x; zprimel y; natl x = natl y |] ==> x = y
lemma zprimel_conversion:
primel l = zprimel (intl l)
lemma zprod_pos:
0 ≤ zprod (intl l)
lemma zprod_conversion:
prod l = nat (zprod (intl l))
lemma zprodl_zprimel_pos:
zprimel pl ==> 0 ≤ zprod pl
lemma zprodl_zprimel_gr_0:
zprimel pl ==> 0 < zprod pl
lemma znondec_conversion:
nondec l = znondec (intl l)
lemma znondec_distrib:
znondec (a # list) ==> znondec list
lemma temp:
1 < p ==> ¬ p dvd 1
lemma zprime_zdvd_zmult_list:
[| p ∈ zprime; p dvd zprod xs |] ==> ∃m. m ∈ set xs ∧ p dvd m
lemma zprimes_eq:
[| p ∈ zprime; q ∈ zprime; p dvd q |] ==> p = q
lemma zprime_zdvd_eq:
[| zprimel (x # xs); zprimel ys; m ∈ set ys; x dvd m |] ==> x = m
lemma zfactor_unique:
[| zprimel (intl x); zprimel (intl y); znondec (intl x); znondec (intl y); zprod (intl x) = zprod (intl y) |] ==> x = y
lemma aux1:
1 < n ==> ∃!l. zprimel (intl l) ∧ znondec (intl l) ∧ zprod (intl l) = n
theorem unique_zprime_factorization:
1 < n ==> ∃!l. zprimel l ∧ znondec l ∧ zprod l = n