Up to index of Isabelle/HOL/HOL-Complex/NumberTheory
theory PrimeFactorsList = IntFactorization:(* Title: PrimeFactorsList.thy
Author: David Gray and Jeremy Avigad
*)
header {* Primes and multiplicity *}
theory PrimeFactorsList = IntFactorization:;
(********************************************)
(* Some initial sorting stuff for lists *)
(* which will later be quite useful *)
(********************************************)
consts
zinsert :: "int => int list => int list"
zsort :: "int list => int list";
primrec
"zinsert x [] = [x]"
"zinsert x (h # t) = (if (x <= h) then (x # (h#t))
else (h # (zinsert x t)))";
primrec
"zsort [] = []"
"zsort (h # t) = (zinsert h (zsort t))";
(* the actual stuff *)
consts
pfactors :: "int => int list"
numoccurs :: "'a => 'a list => nat"
multiplicity :: "int => int => nat";
primrec
"numoccurs x [] = 0"
"numoccurs x (h # t) = (if (x = h) then 1 + (numoccurs x t)
else (numoccurs x t))";
defs
pfactors_def: "pfactors n ==
(if (1 < n) then
(THE l. (zprimel l & znondec l & zprod l = n))
else [])"
multiplicity_def: "multiplicity p n == (numoccurs p (pfactors n))";
subsection {* Show that zinsert and zsort play well with others *}
lemma znondec_zinsert [rule_format]: "znondec (l) --> znondec (zinsert a (l))";
apply (induct l, force);
apply (case_tac list, auto);
done;
lemma znondec_zsort: "znondec (zsort l)";
by (induct l, auto simp add: znondec_zinsert);
lemma zprimel_zinsert [rule_format]: "zprimel l --> a : zprime --> zprimel (zinsert a (l))";
by (induct l, auto simp add: zprimel_def);
lemma zprimel_zsort [rule_format]: "zprimel l --> zprimel (zsort l)";
apply (induct l, force, clarify);
apply (frule zprimel_distrib2);
apply (drule zprimel_distrib1, clarify);
apply (auto simp add: zprimel_zinsert);
done;
lemma zprod_zinsert: "(a * zprod l) = (zprod (zinsert a l))";
by (induct l, auto);
lemma zprod_zsort: "zprod l = zprod (zsort l)";
by (induct l, auto simp add: zprod_zinsert);
lemma numoccurs_zinsert1: "numoccurs a l + 1 = numoccurs a (zinsert a l)";
by (induct l, auto);
lemma numoccurs_zinsert2: "a ~= p ==> numoccurs p l = numoccurs p (zinsert a l)";
by (induct l, auto);
lemma numoccurs_zsort: "numoccurs p l = numoccurs p (zsort l)";
apply (induct l, auto simp add: numoccurs_zinsert2);
apply (insert numoccurs_zinsert1, auto);
done;
lemma length_zinsert: "length l + 1 = length (zinsert a l)";
by (induct l, auto);
lemma length_zsort: "length l = length (zsort l)";
by (insert length_zinsert, induct l, auto);
subsection {* Some more intial properties for zprime and zprod *}
lemma zprimel_cons: "(zprimel lista & zprimel listb) = zprimel (lista @ listb)";
by (auto simp add: zprimel_def);
lemma aux1 [rule_format]: "zprod lista * zprod list = zprod (lista @ list) -->
zprod lista * (a * zprod list) = zprod (lista @ a # list)";
by (induct lista, auto);
lemma zprod_cons: "zprod lista * zprod listb = zprod (lista @ listb)";
by (induct listb, auto simp add: aux1);
lemma zprod_zprime_prop [rule_format]: "p:zprime ==> zprimel l --> p dvd (zprod l) --> p mem l";
proof (induct l, auto);
assume "p :zprime" and "p dvd 1";
thus "False";
apply (auto simp add: zprime_def);
apply (drule zdvd_bounds, auto);
done;
next;
fix a and list;
assume "zprimel (a # list)" and "~ zprimel list"
thus "p mem list" by (simp add: zprimel_def);
next;
fix a and list;
assume p1:"p:zprime" and " zprimel (a # list)" and "p dvd a * zprod list" and "~ p dvd zprod list";
with zprime_zdvd_zmult_better have p2:"p dvd a" by auto;
have p3: "a: zprime" by (insert prems, auto simp add: zprimel_def);
have "p = a";
apply (insert p1 p2 p3);
apply (rule_tac zprimes_eq, auto);
done;
moreover assume "a ~= p";
ultimately show "p mem list" by auto;
qed;
subsection {* Basic properties of numoccurs *}
lemma not_mem_numoccurs_eq_0 [rule_format]: "~(a mem list) --> numoccurs a list = 0";
by (induct list, auto);
lemma mem_numoccurs_gr_0 [rule_format]: "a mem list --> 0 < numoccurs a list";
by (induct list, auto);
lemma zprimel_not_zprime_numoccrs_eq_0 [rule_format]: "zprimel l --> p ~: zprime --> numoccurs p l = 0";
by (induct l, auto simp add: zprimel_def);
lemma aux2 [rule_format]: "numoccurs a (l1 @ list) = numoccurs a l1 + numoccurs a list
--> numoccurs a (l1 @ aa # list) = numoccurs a l1 + numoccurs a (aa # list)";
by (induct l1, auto);
lemma numoccurs_concat_zplus: "numoccurs a (l1 @ l2) = numoccurs a l1 + numoccurs a l2";
by (induct l2, auto simp add: aux2);
subsection {* More Properties for numoccurs *}
lemma aux3: "(ALL p. numoccurs p (a # l1) <= numoccurs p (a # l2)) =
(ALL p. numoccurs p l1 <= numoccurs p l2)";
by (auto);
lemma aux4 [rule_format]: "znondec (b # aa # list) --> znondec (b # list)";
by (case_tac list, auto);
lemma znondec_l_numoccurs [rule_format]: "a < b --> znondec (b # list) --> numoccurs a (b # list) = 0";
apply (induct list, force, clarify);
apply (frule aux4);
apply (drule mp, auto);
done;
lemma aux5: "[| znondec (b # lista); a < b;
ALL p. numoccurs p (b # lista) <= numoccurs p (a # listb);
ALL l1. znondec l1 & (ALL p. numoccurs p l1 <= numoccurs p listb) --> zprod l1 dvd zprod listb |]
==> zprod (b # lista) dvd zprod listb";
apply (drule_tac x = "b # lista" in spec);
apply (erule mp);
apply (rule conjI, force);
apply (rule allI);
apply (drule_tac x = p in spec);
apply (case_tac "p = a");
apply (drule znondec_l_numoccurs, auto);
done;
lemma aux6 [rule_format]: "znondec l2 -->
(ALL l1. (znondec l1 & (ALL p. (numoccurs p l1 <= numoccurs p l2))) -->
zprod l1 dvd zprod l2)";
apply (induct l2, clarify);
apply (case_tac l1, force, clarify);
apply (drule_tac x = a in spec, force, clarify);
apply (frule znondec_distrib);
apply (drule mp, force);
apply (case_tac l1, force, clarify);
apply (case_tac "aa = a", clarify);
apply (drule_tac x = "lista" in spec);
apply (drule znondec_distrib)+;
apply (clarsimp simp only: aux3, clarsimp);
apply (subgoal_tac "a dvd a");
apply (simp add: zdvd_zmult_mono, force);
apply (case_tac "a < aa");
apply (frule_tac a = a and b = aa and lista = lista and listb = list in aux5);
apply (force)+;
apply (simp add: zdvd_zmult);
apply (subgoal_tac "aa < a");
apply (frule znondec_l_numoccurs, force);
apply (drule_tac x = aa in spec);
apply (force)+;
done;
lemma znondec_imp_zprod_zdvd: "[| znondec lista; znondec listb;
ALL p. numoccurs p lista <= numoccurs p listb |] ==>
zprod lista dvd zprod listb";
by (auto simp add: aux6);
lemma zpower_numoccurs_zdvd_zprod: "p^(numoccurs p l) dvd zprod l";
by (induct l, auto simp add: dvd_def);
lemma aux7: "ALL k. p ^ k dvd zprod l --> zprimel l --> p:zprime --> k <= (numoccurs p l)";
apply (induct l, auto); defer;
apply (case_tac k, auto);defer;defer;
proof-;
fix k;
assume "p : zprime";
then have p1: "1 < p" by (auto simp add: zprime_def);
then have "0 <= p ^ k";
by (induct k, auto simp add: zero_le_mult_iff);
moreover assume "p^k dvd 1";
ultimately have "p ^ k = 1";
by (auto simp: ge_0_zdvd_1);
then show "k = 0";
apply (induct k);
apply (insert p1);
apply (auto simp add:zmult_eq_1_iff);
done;
next;
fix list; fix nat;
assume IH: "ALL k. p ^ k dvd zprod list --> zprimel list --> k <= numoccurs p list" and
p1: "p * p ^ nat dvd p * zprod list" and
p2: "zprimel (p # list)" and p3: "p : zprime";
have "p ^ nat dvd zprod list";
proof-;
from p3 have "p ~= 0" by (auto simp add: zprime_def);
with p1 show "p ^ nat dvd zprod list";
by (rule_tac a = p in ne_0_zdvd_prop, auto);
qed;
moreover from p2 have "zprimel list";
by (auto simp add: zprimel_def);
ultimately show "nat <= numoccurs p list";
by (auto simp add: IH);
next;
fix a; fix list; fix k;
assume IH: "ALL k. p ^ k dvd zprod list --> zprimel list --> k <= numoccurs p list" and
p1: "p ~= a" and p2: "p ^ k dvd a * zprod list" and
p3: "zprimel (a # list)" and p4: "p : zprime";
from p3 have "a:zprime" by (auto simp add: zprimel_def);
with p1 p4 have "~ p dvd a";
apply (auto simp add: zprime_def);
apply (drule_tac x = a in allE, force);
apply (drule_tac x = p in allE, auto);
done;
moreover note p4 p2;
ultimately have "p ^ k dvd zprod list";
apply (rule_tac p = p in zprime_zdvd_zpower);
apply (auto simp add: zmult_ac);
done;
moreover from p3 have "zprimel list"
by (auto simp add: zprimel_def);
ultimately show "k <= numoccurs p list";
by (auto simp add: IH);
qed;
lemma zpower_zdvd_zprod_impl_numoccurs [rule_format]: "p ^ k dvd zprod l --> zprimel l --> p:zprime --> k <= (numoccurs p l)";
by (auto simp add: aux7);
subsection {* A Few Useful Lemmas *}
lemma zprimel_zprod_eq_1_impl_empty [rule_format]: "zprimel l --> zprod l = 1 --> l = []";
apply (induct l);
apply (auto simp add: zprimel_def zprime_def pos_zmult_eq_1_iff);
done;
lemma zprimel_zprod_gr_1_impl_not_empty [rule_format]: "zprimel l --> 1 < zprod l --> l ~= []";
apply (induct l);
apply (auto simp add: zprimel_def zprime_def pos_zmult_eq_1_iff);
done;
subsection {* Basic Properties about pfactors (from Unique Factorization) *}
lemma pfactors_simp_prop: "[|zprimel l; znondec l; zprod l = n |] ==> pfactors n = l";
apply (simp add: pfactors_def, auto);
apply (rule the1_equality);
apply (auto simp add: unique_zprime_factorization);
apply (frule zprodl_zprimel_gr_0);
apply (case_tac "zprod l = 1");
apply (auto simp add: zprimel_zprod_eq_1_impl_empty [THEN sym]);
done;
lemma pfactors_fundamental_prop: "1 < n ==> zprimel (pfactors n) & znondec (pfactors n) &
zprod (pfactors n) = n";
apply (simp add: pfactors_def);
apply (rule theI', drule unique_zprime_factorization);
apply (auto);
done;
lemma pfactors_zprimel: "zprimel (pfactors n)";
apply (case_tac "1 < n");
apply (auto simp add: pfactors_fundamental_prop);
apply (auto simp add: zprimel_def pfactors_def);
done;
lemma pfactors_znondec: "znondec(pfactors n)";
apply (case_tac "1 < n");
apply (auto simp add: pfactors_fundamental_prop);
apply (auto simp add: pfactors_def);
done;
lemma pfactors_zprod: "1 <= n ==> zprod (pfactors n) = n";
apply (case_tac "1 < n");
apply (auto simp add: pfactors_fundamental_prop);
apply (auto simp add: pfactors_def);
done;
lemma pfactors_le_1: "n <= 1 ==> pfactors n = []";
by (auto simp add: pfactors_def);
lemma pfactors_gr_1: "1 < n ==> pfactors n ~= []";
proof-;
assume "1 < n";
also have "n = zprod( pfactors n)";
by (insert prems, auto simp add: pfactors_zprod);
finally have "1 < zprod( pfactors n)" .;
moreover have "zprimel (pfactors n)";
by( auto simp add: pfactors_zprimel);
ultimately show ?thesis;
by (auto simp add:zprimel_zprod_gr_1_impl_not_empty);
qed;
lemmas pfactors_ac = pfactors_le_1 pfactors_gr_1 pfactors_zprimel
pfactors_znondec pfactors_zprod;
subsection {* More Properties About pfactors *}
lemma pfactors_zprime: "p:zprime ==> pfactors p = [p]";
apply (auto simp add: pfactors_def);
apply (rule the1_equality);
apply (drule unique_zprime_factorization);
apply (auto simp add: zprime_def zprimel_def);
done;
lemma length_pfactors_zprime: "p:zprime ==> length (pfactors p) = 1";
by (auto simp add: pfactors_zprime);
lemma zprod_zdvd [rule_format]: "x mem list --> x dvd (zprod list)";
by (induct list, auto simp add: dvd_def);
lemma mem_pfactors_imp_zdvd: "[| 1 <= n; p mem (pfactors n) |] ==> p dvd n";
proof-;
assume "1 <= n" and "p mem (pfactors n)";
then have "p dvd (zprod (pfactors n))";
by (auto simp add: zprod_zdvd);
also have "zprod (pfactors n) = n"
by (insert prems, auto simp add: pfactors_ac);
finally show ?thesis;.;
qed;
lemma zdvd_imp_mem_pfactors: "[| 1 <= n; p:zprime; p dvd n |] ==> p mem (pfactors n)";
proof-;
assume "1 <= n" and "p dvd n";
then have "p dvd zprod (pfactors n)";
by (auto simp add: pfactors_ac);
moreover have "zprimel (pfactors n)";
by (insert prems, auto simp add: pfactors_zprimel);
moreover assume "p:zprime";
ultimately show "p mem (pfactors n)";
by (auto simp add: zprod_zprime_prop);
qed;
lemma pfactors_zsort_cons: "[| 1 <= a; 1 <= b |] ==> pfactors (a * b) = zsort((pfactors a) @ (pfactors b))";
apply (rule pfactors_simp_prop);
proof-;
have "zprimel (pfactors a)" and "zprimel (pfactors b)";
by (auto simp add: pfactors_ac);
then have "zprimel (pfactors a @ pfactors b)";
by (insert zprimel_cons, auto);
thus "zprimel (zsort (pfactors a @ pfactors b))";
by (auto simp add: zprimel_zsort);
next;
show "znondec (zsort (pfactors a @ pfactors b))";
by (auto simp add: znondec_zsort);
next;
assume "1 <= a" and "1 <= b";
have "zprod (zsort (pfactors a @ pfactors b)) = zprod (pfactors a @ pfactors b)";
by (auto simp add: zprod_zsort [THEN sym]);
also have "... = zprod (pfactors a) * zprod (pfactors b)";
by (auto simp add: zprod_cons [THEN sym]);
also have "zprod (pfactors a) = a";
by (insert prems, auto simp add: pfactors_ac);
also have "zprod (pfactors b) = b";
by (insert prems, auto simp add: pfactors_ac);
finally show "zprod (zsort (pfactors a @ pfactors b)) = a * b" by auto;
qed;
lemma pfactors_zmult_length: "[| 1 <= a; 1 <= b |] ==>
length (pfactors (a * b)) = length(pfactors a) + length(pfactors b)";
proof-;
assume "1 <= a" and "1 <= b";
then have "length(pfactors (a * b)) = length(zsort((pfactors a) @ (pfactors b)))";
by (auto simp add: pfactors_zsort_cons);
also have "... = length(pfactors a @ pfactors b)";
by (insert length_zsort [of "pfactors a @ pfactors b"], auto);
also have "... = length (pfactors a) + length (pfactors b)";
by (auto);
finally show ?thesis by auto;
qed;
lemma pfactors_zprime_zmult_length: "[| 1 <= d; p:zprime|] ==>
length (pfactors (d * p)) = length(pfactors d) + 1";
proof-;
assume "1 <= d";
assume "p : zprime" then have "1 <= p" by (auto simp add: zprime_def);
then have "length (pfactors (d * p)) = length(pfactors d) + length(pfactors p)";
by (auto simp add: prems pfactors_zmult_length);
also have "length (pfactors p) = 1";
by (insert prems, auto simp add: pfactors_zprime);
finally show ?thesis by auto;
qed;
subsection {* Properties for Multiplicity *}
lemma multiplicity_base: "p :zprime ==> multiplicity p p = 1";
by (auto simp add: multiplicity_def pfactors_zprime);
lemma multiplicity_zmult_distrib: "[| 1 <= a; 1 <= b |] ==>
multiplicity p (a * b) = multiplicity p a + multiplicity p b";
apply (auto simp add: multiplicity_def);
proof-;
assume "1 <= a" and "1 <= b";
then have "pfactors (a * b) = zsort((pfactors a) @ (pfactors b))";
by (auto simp add: pfactors_zsort_cons);
then have "numoccurs p (pfactors (a * b)) = numoccurs p (zsort((pfactors a) @ (pfactors b)))";
by (auto);
also have "... = numoccurs p ((pfactors a) @ (pfactors b))";
by (auto simp add: numoccurs_zsort [THEN sym]);
also have "... = numoccurs p (pfactors a) + numoccurs p (pfactors b)";
by (auto simp add: numoccurs_concat_zplus);
finally show "numoccurs p (pfactors (a * b)) = numoccurs p (pfactors a) + numoccurs p (pfactors b)"
by auto;
qed;
lemma multiplicity_zpower_prop: "p:zprime ==> multiplicity p (p^k) = k";
apply (induct k, simp add: multiplicity_def pfactors_def);
proof (auto);
fix n;
assume "multiplicity p (p ^ n) = n";
assume "p:zprime" then have p1: "1 <= p" by (auto simp add: zprime_def);
then have "1 <= p ^ n" by (auto simp add: ge_1_imp_zpower_ge_1);
then have "multiplicity p (p * p ^ n) = multiplicity p p + multiplicity p (p ^ n)";
by (insert p1 multiplicity_zmult_distrib, auto);
also have "multiplicity p p = 1";
by (insert prems multiplicity_base, auto);
also have "multiplicity p (p ^ n) = n" by (auto simp add: prems);
finally show "multiplicity p (p * p ^ n) = Suc n" by auto;
qed;
lemma multiplicity_zdvd: "p ^ (multiplicity p n) dvd n";
proof (case_tac "1 < n");
assume "1 < n";
have "p^(numoccurs p (pfactors n)) dvd zprod (pfactors n)";
by ( auto simp add: zpower_numoccurs_zdvd_zprod);
also have "zprod (pfactors n) = n";
by (insert prems, auto simp add: pfactors_ac);
also have "numoccurs p (pfactors n) = multiplicity p n";
by (auto simp add: multiplicity_def);
finally show ?thesis .;
next;
assume "~(1 < n)";
then have p1: "n <= 1" by auto;
have "p ^ 0 dvd n" by auto;
also have "0 = multiplicity p n";
by (insert p1, auto simp add: multiplicity_def pfactors_def);
finally show ?thesis .;
qed;
lemma not_zprime_multiplicity_eq_0: "[| p ~: zprime |] ==> multiplicity p n = 0";
apply (insert pfactors_zprimel [of n]);
apply (auto simp add: multiplicity_def zprimel_not_zprime_numoccrs_eq_0);
done;
lemma aux8: "k <= multiplicity p n ==> p ^ k dvd n";
proof-;
assume "k <= multiplicity p n";
then have "p ^ k dvd p ^ multiplicity p n";
by (auto simp add: le_imp_zpower_zdvd);
moreover from multiplicity_zdvd have "p ^ multiplicity p n dvd n"
by auto;
ultimately show ?thesis by (auto simp add: dvd_def);
qed;
lemma aux9: "[| 0 < n; p:zprime; p ^ k dvd n |]==> k <= multiplicity p n";
apply (auto simp add: multiplicity_def);
apply (case_tac "1 < n");
apply (rule zpower_zdvd_zprod_impl_numoccurs);
apply (auto simp add: pfactors_ac);
apply (subgoal_tac "n <= 1", auto);
apply (case_tac "n = 1", auto);
proof-;
assume "p:zprime"
then have p1: "1 < p" by (auto simp add: zprime_def);
then have "0 <= p ^ k";
by (induct k, auto simp add: zero_le_mult_iff);
moreover assume "p^k dvd 1";
ultimately have "p ^ k = 1";
by (auto simp: ge_0_zdvd_1);
then show "k = 0";
apply (induct k, insert p1);
apply (auto simp add:zmult_eq_1_iff);
done;
qed;
lemma multiplicity_zpower_zdvd: "[| 0 < n; p:zprime |] ==> (k <= multiplicity p n) = (p ^ k dvd n)";
by (auto simp add: aux8, simp add: aux9);
lemma zdvd_zprime_imp_multiplicity_ge_1: "[| 0 < n; p dvd n; p:zprime |] ==> 1 <= multiplicity p n";
by (insert multiplicity_zpower_zdvd [of n p 1], auto);
lemma multiplicity_eq_1_imp_zdvd: "[| multiplicity p n = 1 |] ==> p dvd n";
apply (case_tac "0 < n");
proof-;
assume "multiplicity p n = 1";
then have "multiplicity p n ~= 0" by auto;
then have p1: "p : zprime";
by (insert not_zprime_multiplicity_eq_0 [of p n], auto);
moreover assume "0 < n";
moreover have "1 <= multiplicity p n" by (insert prems, auto);
ultimately have "(p ^ 1 dvd n)";
by (insert multiplicity_zpower_zdvd [of n p 1], auto);
thus ?thesis by auto;
next;
assume "multiplicity p n = 1" and "~ 0 < n";
thus ?thesis by (simp add: multiplicity_def pfactors_def);
qed;
lemma zdvd_imp_multiplicity_le: "[| 0 < n; m dvd n |] ==> ALL p. (multiplicity p m <= multiplicity p n)";
proof (clarify, case_tac "p : zprime");
fix p;
assume "m dvd n";
then have "p ^ (multiplicity p m) dvd m";
by (auto simp add: multiplicity_zdvd);
then have "p ^ (multiplicity p m) dvd n";
by (insert prems zdvd_trans [of "p ^ (multiplicity p m)" m n], auto);
moreover assume "p : zprime" and "0 < n";
ultimately show "(multiplicity p m <= multiplicity p n)";
by (insert multiplicity_zpower_zdvd [of n p "multiplicity p m"], auto);
next;
fix p;
assume "p ~: zprime";
thus "multiplicity p m <= multiplicity p n";
by (auto simp add: not_zprime_multiplicity_eq_0);
qed;
lemma multiplicity_le_imp_zdvd: "[| 0 < m; 0 < n;
ALL p. (multiplicity p m <= multiplicity p n) |] ==>
m dvd n";
proof-;
assume "0 < m" and "0 < n";
assume "ALL p. (multiplicity p m <= multiplicity p n)";
then have "ALL p. (numoccurs p (pfactors m) <= numoccurs p (pfactors n))"
by (auto simp add: multiplicity_def);
moreover have "znondec (pfactors m)" by (auto simp add: pfactors_ac);
moreover have "znondec (pfactors n)" by (auto simp add: pfactors_ac);
moreover note znondec_imp_zprod_zdvd;
ultimately have "zprod (pfactors m) dvd zprod (pfactors n)" by auto;
also have "zprod (pfactors m) = m" by (insert prems, auto simp add: pfactors_ac);
also have "zprod (pfactors n) = n" by (insert prems, auto simp add: pfactors_ac);
finally show ?thesis .;
qed;
(* A useful lemma *)
lemma p_neq_q_impl_nzdvd: "[| p ~= q; p:zprime; q:zprime |] ==> ~(p dvd q)";
proof (auto simp add: zprime_def);
assume "1 < p" and "p dvd q" and "ALL m. 0 <= m & m dvd q --> m = 1 | m = q";
then have "p = q" by (drule_tac x = p in allE, auto);
moreover assume "p ~= q";
ultimately show False by auto;
qed;
(* Another useful lemma *)
lemma multiplicity_p_1_eq_0: "multiplicity p 1 = 0";
by (auto simp add: multiplicity_def pfactors_def);
(* This should replace zdvd_zprime_imp_multiplicity_ge_1 in PrimeFactorsList *)
lemma zdvd_zprime_multiplicity_ge_1: "[| 0 < n; p:zprime |] ==> (p dvd n) = (1 <= multiplicity p n)";
by (insert multiplicity_zpower_zdvd [of n p 1], auto);
(* Now follow J's notes -- more or less... *)
lemma finite_prime_divisors: "0 < n ==> finite {p. p:zprime & p dvd n}";
proof-;
assume "0 < n";
then have "{p. p:zprime & p dvd n} <= {0..n}";
apply (auto simp add: zprime_def);
apply (frule zdvd_bounds, auto);
done;
moreover have "finite {0..n}" by auto;
ultimately show ?thesis by (auto simp add: finite_subset);
qed;
lemma zdvd_imp_m_eq_n: "[| (0::int) < m; 0 < n; m dvd n; n dvd m |] ==> m = n";
apply (auto simp add: dvd_def);
proof-;
fix k and ka;
assume "0 < m" and "0 < m * k";
then have "0 < k" by (elim zero_less_mult_pos);
moreover assume "k * ka = 1";
ultimately show "k = 1" by (auto simp add: pos_zmult_eq_1_iff);
qed;
lemma multiplicity_imp_m_eq_n: "[| (0::int) < m; 0 < n;
ALL p. (multiplicity p m) = (multiplicity p n) |] ==> m = n";
proof-;
assume "ALL p. multiplicity p m = multiplicity p n"
then have "ALL p. multiplicity p m <= multiplicity p n" and
"ALL p. multiplicity p n <= multiplicity p m" by auto;
moreover assume "0 < m" and "0 < n";
ultimately have "m dvd n" and "n dvd m" by (auto simp add: multiplicity_le_imp_zdvd);
with prems show "m = n" by (auto simp add: zdvd_imp_m_eq_n);
qed;
lemma aux2: "finite F ==> ALL a:F. 0 < a ==> (0::int) < setprod (%q. q ^ g q x) (F::int set)";
by (induct F rule: finite_induct, auto simp add: mult_pos zero_less_power);
lemma aux3: "[| finite A; 0 < p; ALL a:A. 0 < a |] ==>
multiplicity p (setprod (%q. q ^ (g q x)) A) =
setsum (%q. multiplicity p (q ^ (g q x))) A";
apply (induct A rule: finite_induct, auto simp add: multiplicity_p_1_eq_0);
proof-;
fix F and xa;
assume "finite (F::int set)" and "ALL x:F. 0 < x" and "(0::int) < xa";
then have "0 < xa ^ (g xa x)" by (auto simp add: zero_less_power);
moreover have "0 < setprod (%q. q ^ g q x) F";
by (insert prems, auto simp add: aux2);
ultimately have "1 <= xa ^ (g xa x)" and "1 <= setprod (%q. q ^ g q x) F" by auto;
then have "multiplicity p (xa ^ g xa x * setprod (%q. q ^ g q x) F) =
multiplicity p (xa ^ g xa x) + multiplicity p (setprod (%q. q ^ g q x) F)";
by (rule multiplicity_zmult_distrib);
also assume "multiplicity p (setprod (%q. q ^ g q x) F) = (∑q:F. multiplicity p (q ^ g q x))";
finally show "multiplicity p (xa ^ g xa x * setprod (%q. q ^ g q x) F) =
multiplicity p (xa ^ g xa x) + (∑q:F. multiplicity p (q ^ g q x))" .;
qed;
lemma multiplicity_zpower_zmult: "0 < x ==> (multiplicity p (x ^ n)) = n * (multiplicity p x)";
apply (induct n, auto simp add: multiplicity_p_1_eq_0);
proof-;
fix n;
assume "0 < x";
then have "0 < x ^ n" by (induct n, auto simp add: mult_pos);
then have "multiplicity p (x * x ^ n) = (multiplicity p x) + (multiplicity p (x^n))";
by (insert prems, auto simp add: multiplicity_zmult_distrib);
also assume "multiplicity p (x ^ n) = n * multiplicity p x";
finally show "multiplicity p (x * x ^ n) = multiplicity p x + n * multiplicity p x".;
qed;
lemma p_neq_q_multiplicity_eq_0: "[| q ~= p; p:zprime; q:zprime |] ==> multiplicity p q = 0";
proof-;
assume "q ~= p" and "p : zprime" and "q : zprime";
then have "~(p dvd q)" by (auto simp add: p_neq_q_impl_nzdvd);
moreover have "0 < q" by (insert prems, auto simp add: zprime_def);
ultimately have "~(1 <= multiplicity p q)";
by (auto simp add: prems zdvd_zprime_multiplicity_ge_1);
thus ?thesis by auto;
qed;
lemma p_neq_q_multiplicity_zpower_eq_0: "[| q ~= p; p:zprime; q:zprime |] ==> multiplicity p (q ^ n) = 0";
proof-;
assume "q ~= p" and "p:zprime" and "q:zprime";
then have "0 < q" by (auto simp add: zprime_def);
then have "(multiplicity p (q ^ n)) = n * (multiplicity p q)"
by (auto simp add: multiplicity_zpower_zmult);
also have "multiplicity p q = 0" by (insert prems, auto simp add: p_neq_q_multiplicity_eq_0);
finally show ?thesis by auto;
qed;
lemma finite_A_setsum_eq_0: "finite A ==> ALL x:A. f x = 0 ==> setsum f A = (0::int)";
by (induct A rule: finite_induct, auto);
lemma multiplicity_setprod_eq_0: "[| finite A; ALL p:A. (p:zprime); p ~: A; p:zprime |] ==>
multiplicity p (setprod (%q. q ^ (g q x)) A) = 0";
proof-;
assume "finite A" and "ALL p:A. p : zprime" and "p ~:A" and "p:zprime";
moreover have "0 < p" and "ALL p:A. 0 < p" by (insert prems, auto simp add: zprime_def);
ultimately have "multiplicity p (setprod (%q. q ^ (g q x)) A) =
setsum (%q. multiplicity p (q ^ (g q x))) A";
by (auto simp add: aux3);
also have "... = 0";
apply (insert prems, auto simp add: finite_A_setsum_eq_0);
apply (rule p_neq_q_multiplicity_zpower_eq_0, auto);
done;
finally show ?thesis .;
qed;
lemma multiplicity_zdvd_setprod_eq_n: "[| (0::int) < n; q:zprime; q dvd n |] ==>
multiplicity q (setprod (%p. p^(multiplicity p n)) {p. p: zprime & p dvd n}) =
multiplicity q n";
proof-;
assume "0 < n" and "q:zprime" and "q dvd n";
have p1: "finite {p. p: zprime & p dvd n & q ~= p}";
apply (insert finite_prime_divisors [of n] prems);
apply (subgoal_tac "{p. p: zprime & p dvd n & q ~= p} <= {p. p:zprime & p dvd n}");
apply (auto simp add: finite_subset);
done;
have "{p. p:zprime & p dvd n} = insert q {p . p:zprime & p dvd n & q ~= p}";
by (insert prems, auto);
then have "multiplicity q (setprod (%p. p^(multiplicity p n)) {p. p: zprime & p dvd n}) =
multiplicity q (setprod (%p. p^(multiplicity p n)) (insert q {p. p: zprime & p dvd n & q ~= p}))";
by auto;
also have "(setprod (%p. p^(multiplicity p n)) (insert q {p. p: zprime & p dvd n & q ~= p})) =
(%p. p^(multiplicity p n)) q * setprod (%p. p^(multiplicity p n)) {p. p: zprime & p dvd n & q ~= p}";
proof-;
note p1;
moreover have "q ~: {p. p: zprime & p dvd n & q ~= p}" by auto;
ultimately show ?thesis by (auto simp add: setprod_insert);
qed;
finally have "multiplicity q (setprod (%p. p ^ multiplicity p n) {p. p : zprime & p dvd n}) =
multiplicity q (q ^ multiplicity q n *
setprod (%p. p ^ multiplicity p n) {p. p : zprime & p dvd n & q ~= p})" .;
also have "... = (multiplicity q (q^(multiplicity q n))) +
(multiplicity q (setprod (%p. p^(multiplicity p n)) {p. p: zprime & p dvd n & q ~= p}))";
proof-;
have p2: "ALL p:{p. p : zprime & p dvd n & q ~= p}. 0 < p"; by (auto simp add: zprime_def);
have "0 < q" by (insert prems, auto simp add: zprime_def);
then have "0 < q ^ multiplicity q n" by (auto simp add: zero_less_power);
moreover have "0 < setprod (%p. p ^ multiplicity p n) {p. p : zprime & p dvd n & q ~= p}";
apply (insert p1 p2 prems);
apply (induct "{p. p : zprime & p dvd n & q ~= p}" rule: finite_induct);
apply (auto simp add: mult_pos zero_less_power);
done;
ultimately show ?thesis by (auto simp add: multiplicity_zmult_distrib);
qed;
also have "(multiplicity q (setprod (%p. p^(multiplicity p n)) {p. p: zprime & p dvd n & q ~= p})) = 0";
proof-;
note p1;
moreover have "ALL p:{p. p : zprime & p dvd n & q ~= p}. (p:zprime)" by auto;
moreover have "q ~: {p. p : zprime & p dvd n & q ~= p}" by auto;
moreover have "q:zprime" by (insert prems, auto);
ultimately show ?thesis by (rule multiplicity_setprod_eq_0);
qed;
also have "(multiplicity q (q^(multiplicity q n))) = multiplicity q n";
by (insert prems, auto simp add: multiplicity_zpower_prop);
finally show ?thesis by auto;
qed;
lemma multiplicity_nzdvd_setprod_eq_n: "[| 0 < n; q: zprime; ~(q dvd n) |] ==>
multiplicity q (setprod (%p. p ^ (multiplicity p n)) {p. p:zprime & p dvd n}) =
multiplicity q n";
proof-;
assume "0 < n" and "q: zprime" and "~(q dvd n)";
then have "multiplicity q n = 0" by (insert zdvd_zprime_multiplicity_ge_1, auto);
moreover have "multiplicity q (setprod (%p. p ^ (multiplicity p n)) {p. p:zprime & p dvd n}) = 0";
proof-;
have "finite {p. p:zprime & p dvd n}" by (insert prems, auto simp add: finite_prime_divisors);
moreover have "ALL p:{p. p:zprime & p dvd n}. p:zprime" by (auto);
moreover have "q ~: {p. p:zprime & p dvd n}" by (auto simp add: prems);
moreover note prems;
ultimately show ?thesis;
apply (rule_tac multiplicity_setprod_eq_0);
apply (force)+;
done;
qed;
ultimately show ?thesis by auto;
qed;
lemma multiplicity_setprod_eq_n: "[| 0 < n; q: zprime |] ==>
multiplicity q (setprod (%p. p ^ (multiplicity p n)) {p. p:zprime & p dvd n}) =
multiplicity q n";
apply (case_tac "q dvd n");
apply (auto simp add: multiplicity_nzdvd_setprod_eq_n multiplicity_zdvd_setprod_eq_n);
done;
theorem n_eq_setprod_multiplicity: "0 < n ==> n = setprod (%p. p ^(multiplicity p n)) {p. p:zprime & p dvd n}";
apply (rule multiplicity_imp_m_eq_n, auto);
apply (rule aux2, auto simp add: finite_prime_divisors);
apply (force simp add: zprime_def);
apply (case_tac "p : zprime");
apply (auto simp add: multiplicity_setprod_eq_n [THEN sym] not_zprime_multiplicity_eq_0);
done;
end;
lemma znondec_zinsert:
znondec l ==> znondec (zinsert a l)
lemma znondec_zsort:
znondec (zsort l)
lemma zprimel_zinsert:
[| zprimel l; a ∈ zprime |] ==> zprimel (zinsert a l)
lemma zprimel_zsort:
zprimel l ==> zprimel (zsort l)
lemma zprod_zinsert:
a * zprod l = zprod (zinsert a l)
lemma zprod_zsort:
zprod l = zprod (zsort l)
lemma numoccurs_zinsert1:
numoccurs a l + 1 = numoccurs a (zinsert a l)
lemma numoccurs_zinsert2:
a ≠ p ==> numoccurs p l = numoccurs p (zinsert a l)
lemma numoccurs_zsort:
numoccurs p l = numoccurs p (zsort l)
lemma length_zinsert:
length l + 1 = length (zinsert a l)
lemma length_zsort:
length l = length (zsort l)
lemma zprimel_cons:
(zprimel lista ∧ zprimel listb) = zprimel (lista @ listb)
lemma aux1:
zprod lista * zprod list = zprod (lista @ list) ==> zprod lista * (a * zprod list) = zprod (lista @ a # list)
lemma zprod_cons:
zprod lista * zprod listb = zprod (lista @ listb)
lemma zprod_zprime_prop:
[| p ∈ zprime; zprimel l; p dvd zprod l |] ==> p mem l
lemma not_mem_numoccurs_eq_0:
¬ a mem list ==> numoccurs a list = 0
lemma mem_numoccurs_gr_0:
a mem list ==> 0 < numoccurs a list
lemma zprimel_not_zprime_numoccrs_eq_0:
[| zprimel l; p ∉ zprime |] ==> numoccurs p l = 0
lemma aux2:
numoccurs a (l1 @ list) = numoccurs a l1 + numoccurs a list ==> numoccurs a (l1 @ aa # list) = numoccurs a l1 + numoccurs a (aa # list)
lemma numoccurs_concat_zplus:
numoccurs a (l1 @ l2) = numoccurs a l1 + numoccurs a l2
lemma aux3:
(∀p. numoccurs p (a # l1) ≤ numoccurs p (a # l2)) = (∀p. numoccurs p l1 ≤ numoccurs p l2)
lemma aux4:
znondec (b # aa # list) ==> znondec (b # list)
lemma znondec_l_numoccurs:
[| a < b; znondec (b # list) |] ==> numoccurs a (b # list) = 0
lemma aux5:
[| znondec (b # lista); a < b; ∀p. numoccurs p (b # lista) ≤ numoccurs p (a # listb); ∀l1. znondec l1 ∧ (∀p. numoccurs p l1 ≤ numoccurs p listb) --> zprod l1 dvd zprod listb |] ==> zprod (b # lista) dvd zprod listb
lemma aux6:
[| znondec l2; znondec l1 ∧ (∀p. numoccurs p l1 ≤ numoccurs p l2) |] ==> zprod l1 dvd zprod l2
lemma znondec_imp_zprod_zdvd:
[| znondec lista; znondec listb; ∀p. numoccurs p lista ≤ numoccurs p listb |] ==> zprod lista dvd zprod listb
lemma zpower_numoccurs_zdvd_zprod:
p ^ numoccurs p l dvd zprod l
lemma aux7:
∀k. p ^ k dvd zprod l --> zprimel l --> p ∈ zprime --> k ≤ numoccurs p l
lemma zpower_zdvd_zprod_impl_numoccurs:
[| p ^ k dvd zprod l; zprimel l; p ∈ zprime |] ==> k ≤ numoccurs p l
lemma zprimel_zprod_eq_1_impl_empty:
[| zprimel l; zprod l = 1 |] ==> l = []
lemma zprimel_zprod_gr_1_impl_not_empty:
[| zprimel l; 1 < zprod l |] ==> l ≠ []
lemma pfactors_simp_prop:
[| zprimel l; znondec l; zprod l = n |] ==> pfactors n = l
lemma pfactors_fundamental_prop:
1 < n ==> zprimel (pfactors n) ∧ znondec (pfactors n) ∧ zprod (pfactors n) = n
lemma pfactors_zprimel:
zprimel (pfactors n)
lemma pfactors_znondec:
znondec (pfactors n)
lemma pfactors_zprod:
1 ≤ n ==> zprod (pfactors n) = n
lemma pfactors_le_1:
n ≤ 1 ==> pfactors n = []
lemma pfactors_gr_1:
1 < n ==> pfactors n ≠ []
lemmas pfactors_ac:
n ≤ 1 ==> pfactors n = []
1 < n ==> pfactors n ≠ []
zprimel (pfactors n)
znondec (pfactors n)
1 ≤ n ==> zprod (pfactors n) = n
lemma pfactors_zprime:
p ∈ zprime ==> pfactors p = [p]
lemma length_pfactors_zprime:
p ∈ zprime ==> length (pfactors p) = 1
lemma zprod_zdvd:
x mem list ==> x dvd zprod list
lemma mem_pfactors_imp_zdvd:
[| 1 ≤ n; p mem pfactors n |] ==> p dvd n
lemma zdvd_imp_mem_pfactors:
[| 1 ≤ n; p ∈ zprime; p dvd n |] ==> p mem pfactors n
lemma pfactors_zsort_cons:
[| 1 ≤ a; 1 ≤ b |] ==> pfactors (a * b) = zsort (pfactors a @ pfactors b)
lemma pfactors_zmult_length:
[| 1 ≤ a; 1 ≤ b |] ==> length (pfactors (a * b)) = length (pfactors a) + length (pfactors b)
lemma pfactors_zprime_zmult_length:
[| 1 ≤ d; p ∈ zprime |] ==> length (pfactors (d * p)) = length (pfactors d) + 1
lemma multiplicity_base:
p ∈ zprime ==> multiplicity p p = 1
lemma multiplicity_zmult_distrib:
[| 1 ≤ a; 1 ≤ b |] ==> multiplicity p (a * b) = multiplicity p a + multiplicity p b
lemma multiplicity_zpower_prop:
p ∈ zprime ==> multiplicity p (p ^ k) = k
lemma multiplicity_zdvd:
p ^ multiplicity p n dvd n
lemma not_zprime_multiplicity_eq_0:
p ∉ zprime ==> multiplicity p n = 0
lemma aux8:
k ≤ multiplicity p n ==> p ^ k dvd n
lemma aux9:
[| 0 < n; p ∈ zprime; p ^ k dvd n |] ==> k ≤ multiplicity p n
lemma multiplicity_zpower_zdvd:
[| 0 < n; p ∈ zprime |] ==> (k ≤ multiplicity p n) = (p ^ k dvd n)
lemma zdvd_zprime_imp_multiplicity_ge_1:
[| 0 < n; p dvd n; p ∈ zprime |] ==> 1 ≤ multiplicity p n
lemma multiplicity_eq_1_imp_zdvd:
multiplicity p n = 1 ==> p dvd n
lemma zdvd_imp_multiplicity_le:
[| 0 < n; m dvd n |] ==> ∀p. multiplicity p m ≤ multiplicity p n
lemma multiplicity_le_imp_zdvd:
[| 0 < m; 0 < n; ∀p. multiplicity p m ≤ multiplicity p n |] ==> m dvd n
lemma p_neq_q_impl_nzdvd:
[| p ≠ q; p ∈ zprime; q ∈ zprime |] ==> ¬ p dvd q
lemma multiplicity_p_1_eq_0:
multiplicity p 1 = 0
lemma zdvd_zprime_multiplicity_ge_1:
[| 0 < n; p ∈ zprime |] ==> (p dvd n) = (1 ≤ multiplicity p n)
lemma finite_prime_divisors:
0 < n ==> finite {p. p ∈ zprime ∧ p dvd n}
lemma zdvd_imp_m_eq_n:
[| 0 < m; 0 < n; m dvd n; n dvd m |] ==> m = n
lemma multiplicity_imp_m_eq_n:
[| 0 < m; 0 < n; ∀p. multiplicity p m = multiplicity p n |] ==> m = n
lemma aux2:
[| finite F; ∀a∈F. 0 < a |] ==> 0 < (∏q∈F. q ^ g q x)
lemma aux3:
[| finite A; 0 < p; ∀a∈A. 0 < a |] ==> multiplicity p (∏q∈A. q ^ g q x) = (∑q∈A. multiplicity p (q ^ g q x))
lemma multiplicity_zpower_zmult:
0 < x ==> multiplicity p (x ^ n) = n * multiplicity p x
lemma p_neq_q_multiplicity_eq_0:
[| q ≠ p; p ∈ zprime; q ∈ zprime |] ==> multiplicity p q = 0
lemma p_neq_q_multiplicity_zpower_eq_0:
[| q ≠ p; p ∈ zprime; q ∈ zprime |] ==> multiplicity p (q ^ n) = 0
lemma finite_A_setsum_eq_0:
[| finite A; ∀x∈A. f x = 0 |] ==> setsum f A = 0
lemma multiplicity_setprod_eq_0:
[| finite A; ∀p∈A. p ∈ zprime; p ∉ A; p ∈ zprime |] ==> multiplicity p (∏q∈A. q ^ g q x) = 0
lemma multiplicity_zdvd_setprod_eq_n:
[| 0 < n; q ∈ zprime; q dvd n |] ==> multiplicity q (∏p∈{p. p ∈ zprime ∧ p dvd n}. p ^ multiplicity p n) = multiplicity q n
lemma multiplicity_nzdvd_setprod_eq_n:
[| 0 < n; q ∈ zprime; ¬ q dvd n |] ==> multiplicity q (∏p∈{p. p ∈ zprime ∧ p dvd n}. p ^ multiplicity p n) = multiplicity q n
lemma multiplicity_setprod_eq_n:
[| 0 < n; q ∈ zprime |] ==> multiplicity q (∏p∈{p. p ∈ zprime ∧ p dvd n}. p ^ multiplicity p n) = multiplicity q n
theorem n_eq_setprod_multiplicity:
0 < n ==> n = (∏p∈{p. p ∈ zprime ∧ p dvd n}. p ^ multiplicity p n)