Up to index of Isabelle/HOL/HOL-Complex/NumberTheory
theory Radical = PrimeFactorsList:(* Title: Radical.thy Author: David Gray *) header {* The radical function *} theory Radical = PrimeFactorsList:; consts pdivisors :: "int => int list" rad :: "int => int" squarefree :: "int => bool" subplist :: "int list => int list => bool"; (* Should 0 and 1 be squarefree?? *) defs pdivisors_def: "pdivisors n == remdups(pfactors n)" rad_def: "rad n == zprod(pdivisors n)" squarefree_def: "squarefree n == (if (n <= 1) then True else (distinct (pfactors n)))"; subsection {* Some Initial Properties Involving distinct *} lemma distinct_numoccurs_le_1: "distinct list = (ALL p. (numoccurs p list) <= 1)"; proof-; have "distinct list --> (ALL p. (numoccurs p list) <= 1)"; by (induct list, auto simp add: not_mem_numoccurs_eq_0 set_mem_eq); moreover have "~(distinct list) --> ~(ALL p. (numoccurs p list <= 1)) "; apply (induct list); apply (auto simp add: mem_numoccurs_gr_0 set_mem_eq); apply (rule_tac x = p in exI, auto); done; ultimately show ?thesis by auto; qed; subsection {* Some Initial Properties Involving remdups *} lemma zprimel_remdups_prop [rule_format]: "zprimel l --> zprimel (remdups l)"; by (auto simp add: zprimel_def); lemma aux [rule_format]: "znondec (remdups list) --> znondec (a # list) --> znondec (remdups (a # list))"; apply (induct_tac list, auto); apply (case_tac list, auto); done; lemma znondec_remdups_prop [rule_format]: "znondec l --> znondec (remdups l)"; apply (induct_tac l, force, clarify); apply (subgoal_tac "znondec(remdups list)"); apply (drule aux, force, force); apply (drule znondec_distrib, force); done; lemma not_empty_remdups: "(l ~= []) = (remdups(l) ~= [])"; by (induct l, auto); lemma zprimel_zprod_ge_1 [rule_format]: "zprimel pl --> 1 <= zprod (remdups (pl))"; apply (induct pl, auto simp add: zprimel_def zprime_def); proof-; fix a and list; assume "1 < (a::int)" and "1 <= zprod (remdups list)"; then have b: "1 <= a" by auto; from b have c: "0 <= a"; by arith; have "1 * 1 <= a * zprod (remdups list)"; apply (rule mult_mono); by (auto simp add: prems b c); thus "1 <= a * zprod (remdups list)" by auto; qed; lemma pfactors_zprod_ge_1: "1 <= zprod (remdups (pfactors n))"; apply (rule_tac zprimel_zprod_ge_1); apply (auto simp add: pfactors_ac); done; lemma zprimel_zprod_le [rule_format]: "zprimel pl --> zprod (remdups (pl)) <= zprod (pl)"; proof (induct pl, auto); fix a and list; assume "~ zprimel list" and "a : set list" and "zprimel (a # list)"; thus "zprod (remdups list) <= a * zprod list" by (auto simp add: zprimel_def); next; fix a and list; assume "~ zprimel list" and "a ~: set list" and "zprimel (a # list)"; thus "a * zprod (remdups list) <= a * zprod list" by (auto simp add: zprimel_def); next; fix a and list; assume "zprod (remdups list) <= zprod list" and "zprimel (a # list)"; then have "zprod (remdups list) * 1 <= zprod list * a" apply (intro mult_mono); apply (auto simp add: zprimel_def zprime_def zprodl_zprimel_pos); done; also have "zprod (remdups list) * 1 = zprod (remdups list)" by auto; also have "zprod list * a = a * zprod list" by auto; finally show "zprod (remdups list) <= a * zprod list".; next; fix a and list; assume "zprod (remdups list) <= zprod list" and "a ~: set list" and "zprimel (a # list)"; thus "a * zprod (remdups list) <= a * zprod list" by (auto simp add: zprimel_def zprime_def mult_left_mono); qed; lemma pfactors_zprod_le: "zprod (remdups (pfactors n)) <= zprod (pfactors n)"; apply (rule_tac zprimel_zprod_le); apply (auto simp add: pfactors_ac); done; lemma numoccurs_remdups: "ALL p. numoccurs p (remdups list) <= numoccurs p list"; apply (induct list, auto); apply (drule_tac x = a in spec, auto); done; subsection {* Properties about pdivisors *} lemma pdivisors_zprimel: "zprimel (pdivisors n)"; apply (insert pfactors_zprimel [of n]); apply (drule zprimel_remdups_prop); apply (auto simp add: pdivisors_def); done; lemma pdivisors_znondec: "znondec (pdivisors n)"; apply (insert pfactors_znondec [of n]); apply (drule znondec_remdups_prop); apply (auto simp add: pdivisors_def); done; lemma pdivisors_le_1: "n <= 1 ==> pdivisors n = []"; by (auto simp add: pdivisors_def pfactors_def); lemma pdivisors_gr_1: "1 < n ==> pdivisors n ~= []"; apply (drule pfactors_gr_1); apply (auto simp add: pdivisors_def); apply (auto simp add: not_empty_remdups); done; lemmas pdivisors_ac = pdivisors_le_1 pdivisors_gr_1 pdivisors_znondec pdivisors_zprimel; subsection {* Properties about rad *} lemma le_1_rad_prop: "n <= 1 ==> rad (n) = 1"; by (auto simp add: rad_def pfactors_def pdivisors_def); lemma rad_max: "1 < n ==> rad n <= n"; proof-; assume "1 < n"; note pfactors_zprod_le; also have "zprod (remdups (pfactors n)) = rad n"; by (auto simp add: rad_def pdivisors_def); also have "zprod (pfactors n) = n"; by (insert prems, auto simp add: pfactors_ac); finally show ?thesis .; qed; lemma rad_min_gre_1:"1 <= n ==> 1 <= rad n"; proof-; assume "1 <= n"; note pfactors_zprod_ge_1; also have "zprod (remdups (pfactors n)) = rad n"; by (auto simp add: rad_def pdivisors_def); finally show "1 <= rad n" by auto; qed; lemma rad_min_gr_1:"1 < n ==> 1 < rad n"; proof-; assume "1 < n"; then have "1 <= rad n" by (auto simp add: rad_min_gre_1); moreover have "1 ~= rad n"; proof; assume "1 = rad n"; then have "zprod( pdivisors n) = 1"; by (auto simp add: rad_def); moreover have "zprimel (pdivisors n)"; by (auto simp add: pdivisors_ac); ultimately have "pdivisors n = []"; by (auto simp add: zprimel_zprod_eq_1_impl_empty); moreover have "pdivisors n ~= []"; by (insert prems, auto simp add: pdivisors_ac); ultimately show "False" by auto; qed; ultimately show ?thesis by auto; qed; lemma rad_prime: "p:zprime ==> rad (p) = p"; by (auto simp add: rad_def pfactors_zprime pdivisors_def); lemma pfactors_rad_eq_pdivisors: "pfactors (rad n) = pdivisors n"; by (rule pfactors_simp_prop, auto simp add: pdivisors_ac rad_def); lemma mem_pfactors_mem_pdivisors: "p mem (pfactors n) = p mem (pdivisors n)"; by (auto simp add: pdivisors_def set_mem_eq); lemma zprod_remdups_dvd [rule_format]: "x mem list --> x dvd (zprod(remdups list))"; by (induct list, auto simp add: dvd_def set_mem_eq); lemma mem_pfactors_zdvd_rad: "[| 1 <= n; p mem (pfactors n) |] ==> p dvd (rad n)"; proof-; assume "1 <= n" and "p mem (pfactors n)"; then have "p dvd (zprod(remdups(pfactors n)))"; by (auto simp add: zprod_remdups_dvd); also have "zprod (remdups (pfactors n)) = rad n" by (auto simp add: rad_def pdivisors_def); finally show ?thesis .; qed; lemma mem_pdivisors_dvd_rad: "[| 1 <= n; p mem (pdivisors n) |] ==> p dvd rad(n)"; proof-; assume "1 <= n" and "p mem (pdivisors n)"; then have "p dvd (zprod (pdivisors n))"; by (auto simp add: zprod_zdvd); also have "zprod (pdivisors n) = rad n"; by (auto simp add: prems rad_def); finally show ?thesis;.; qed; lemma dvd_rad_mem_pdivisors: "[| 1 <= n; p:zprime; p dvd rad(n) |] ==> p mem (pdivisors n)"; proof-; assume "1 <= n" and "p dvd rad(n)"; then have "p dvd zprod (pdivisors n)"; by (auto simp add: rad_def); moreover note pdivisors_ac; moreover assume "p:zprime"; ultimately show "p mem (pdivisors n)"; by (auto simp add: zprod_zprime_prop ); qed; lemma zprime_zdvd_rad: "[| p:zprime; 1 <= n |] ==> (p dvd n) = (p dvd rad (n))"; proof; assume "p:zprime" and "1 <= n" and "p dvd n"; then have "p mem (pfactors n)" by (auto simp add: zdvd_imp_mem_pfactors); thus "p dvd rad (n)" by (auto simp add: prems mem_pfactors_zdvd_rad); next; assume "p:zprime" and "1 <= n" and "p dvd rad n"; then have "p mem pdivisors n"; by (auto simp add: dvd_rad_mem_pdivisors); then have "p mem pfactors n"; by (auto simp add: mem_pfactors_mem_pdivisors); thus "p dvd n"; by (insert prems, auto simp add: mem_pfactors_imp_zdvd); qed; lemma rad_squarefree: "1 <= n ==> squarefree (rad (n))"; by (auto simp add: squarefree_def pfactors_rad_eq_pdivisors pdivisors_def); lemma rad_multiplicity_le: "ALL p. multiplicity p (rad n) <= multiplicity p n"; by (auto simp add: multiplicity_def pfactors_rad_eq_pdivisors pdivisors_def numoccurs_remdups); lemma rad_zdvd: "1 <= n ==> rad (n) dvd n"; proof-; assume "1 <= n"; have "ALL p. multiplicity p (rad n) <= multiplicity p n"; by (auto simp add: rad_multiplicity_le); moreover have "1 <= rad n"; by (auto simp add: prems rad_min_gre_1); moreover note multiplicity_le_imp_zdvd; ultimately show ?thesis by (insert prems, auto); qed; subsection {* Properties about squarefree *} lemma squarefree_prop: "squarefree(n) = (ALL p. (multiplicity p n) <= 1)"; apply (simp add: squarefree_def multiplicity_def); apply (auto simp add: distinct_numoccurs_le_1); apply (auto simp add: pfactors_def); done; lemma squarefree_zdvd_imp_zdvd_rad: "[| 1 <= m; 1 <= n; m dvd n; squarefree m |] ==> m dvd rad(n)"; proof-; assume "1 <= m" and "1 <= n"; then have p1: "1 <= rad n" by (auto simp add: rad_min_gre_1); assume "m dvd n" and "squarefree m"; then have "ALL p. (multiplicity p m <= multiplicity p (rad n))"; apply (auto simp add: squarefree_prop); apply (drule_tac x = p in spec); apply (case_tac "multiplicity p m = 0", auto); apply (subgoal_tac "multiplicity p m = 1", auto); proof-; fix p; assume "m dvd n"; assume "multiplicity p m = Suc 0"; then have "multiplicity p m = 1" by auto; then have "p dvd m" by (auto simp add: multiplicity_eq_1_imp_zdvd); then have "p dvd n" by (insert prems zdvd_trans [of p m n], auto); moreover have p2: "p : zprime"; by (insert prems not_zprime_multiplicity_eq_0 [of p m], auto); ultimately have "p dvd rad(n)"; by (insert prems zprime_zdvd_rad [of p n], auto); then have "1 <= multiplicity p (rad n)"; by (insert prems p1 p2 zdvd_zprime_imp_multiplicity_ge_1 [of "rad n" p], auto); thus "Suc 0 <= multiplicity p (rad n)" by auto; qed; thus ?thesis by (insert prems p1, auto simp add: multiplicity_le_imp_zdvd); qed; lemma squarefree_zdvd_impl_squarefree: "[| 0 < n; squarefree n; m dvd n |] ==> squarefree m"; proof-; assume "squarefree n" and "0 < n" and "m dvd n"; then have "ALL p. (multiplicity p n) <= 1" by (auto simp add: squarefree_prop); moreover have "ALL p. (multiplicity p m <= multiplicity p n)"; by (insert prems, auto simp add: zdvd_imp_multiplicity_le); ultimately have "ALL p. (multiplicity p m <= 1)" apply (clarify); apply (drule_tac x = p in spec)+; apply (arith); done; thus "squarefree m" by (auto simp add: squarefree_prop); qed; lemma squarefree_distrib1: "[| 0 < x; 0 < y; squarefree(x * y) |] ==> squarefree (x)"; proof-; assume "0 < x" and "0 < y"; then have "0 < x * y" by (auto simp add: mult_pos); moreover have "x dvd x * y" by auto; moreover assume "squarefree(x * y)"; ultimately show ?thesis; by (insert prems squarefree_zdvd_impl_squarefree [of "x*y" x], auto); qed; lemma squarefree_distrib2: "[| 0 < x; 0 < y; squarefree(x * y) |] ==> squarefree (y)"; proof-; assume "0 < x" and "0 < y"; then have "0 < x * y" by (auto simp add: mult_pos); moreover have "y dvd x * y" by auto; moreover assume "squarefree(x * y)"; ultimately show ?thesis; by (insert prems squarefree_zdvd_impl_squarefree [of "x*y" y], auto); qed; end;
lemma distinct_numoccurs_le_1:
distinct list = (∀p. numoccurs p list ≤ 1)
lemma zprimel_remdups_prop:
zprimel l ==> zprimel (remdups l)
lemma aux:
[| znondec (remdups list); znondec (a # list) |] ==> znondec (remdups (a # list))
lemma znondec_remdups_prop:
znondec l ==> znondec (remdups l)
lemma not_empty_remdups:
(l ≠ []) = (remdups l ≠ [])
lemma zprimel_zprod_ge_1:
zprimel pl ==> 1 ≤ zprod (remdups pl)
lemma pfactors_zprod_ge_1:
1 ≤ zprod (remdups (pfactors n))
lemma zprimel_zprod_le:
zprimel pl ==> zprod (remdups pl) ≤ zprod pl
lemma pfactors_zprod_le:
zprod (remdups (pfactors n)) ≤ zprod (pfactors n)
lemma numoccurs_remdups:
∀p. numoccurs p (remdups list) ≤ numoccurs p list
lemma pdivisors_zprimel:
zprimel (pdivisors n)
lemma pdivisors_znondec:
znondec (pdivisors n)
lemma pdivisors_le_1:
n ≤ 1 ==> pdivisors n = []
lemma pdivisors_gr_1:
1 < n ==> pdivisors n ≠ []
lemmas pdivisors_ac:
n ≤ 1 ==> pdivisors n = []
1 < n ==> pdivisors n ≠ []
znondec (pdivisors n)
zprimel (pdivisors n)
lemma le_1_rad_prop:
n ≤ 1 ==> rad n = 1
lemma rad_max:
1 < n ==> rad n ≤ n
lemma rad_min_gre_1:
1 ≤ n ==> 1 ≤ rad n
lemma rad_min_gr_1:
1 < n ==> 1 < rad n
lemma rad_prime:
p ∈ zprime ==> rad p = p
lemma pfactors_rad_eq_pdivisors:
pfactors (rad n) = pdivisors n
lemma mem_pfactors_mem_pdivisors:
p mem pfactors n = p mem pdivisors n
lemma zprod_remdups_dvd:
x mem list ==> x dvd zprod (remdups list)
lemma mem_pfactors_zdvd_rad:
[| 1 ≤ n; p mem pfactors n |] ==> p dvd rad n
lemma mem_pdivisors_dvd_rad:
[| 1 ≤ n; p mem pdivisors n |] ==> p dvd rad n
lemma dvd_rad_mem_pdivisors:
[| 1 ≤ n; p ∈ zprime; p dvd rad n |] ==> p mem pdivisors n
lemma zprime_zdvd_rad:
[| p ∈ zprime; 1 ≤ n |] ==> (p dvd n) = (p dvd rad n)
lemma rad_squarefree:
1 ≤ n ==> squarefree (rad n)
lemma rad_multiplicity_le:
∀p. multiplicity p (rad n) ≤ multiplicity p n
lemma rad_zdvd:
1 ≤ n ==> rad n dvd n
lemma squarefree_prop:
squarefree n = (∀p. multiplicity p n ≤ 1)
lemma squarefree_zdvd_imp_zdvd_rad:
[| 1 ≤ m; 1 ≤ n; m dvd n; squarefree m |] ==> m dvd rad n
lemma squarefree_zdvd_impl_squarefree:
[| 0 < n; squarefree n; m dvd n |] ==> squarefree m
lemma squarefree_distrib1:
[| 0 < x; 0 < y; squarefree (x * y) |] ==> squarefree x
lemma squarefree_distrib2:
[| 0 < x; 0 < y; squarefree (x * y) |] ==> squarefree y