Theory Radical

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;
    

Some Initial Properties Involving distinct

lemma distinct_numoccurs_le_1:

  distinct list = (∀p. numoccurs p list ≤ 1)

Some Initial Properties Involving remdups

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

Properties about pdivisors

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)

Properties about rad

lemma le_1_rad_prop:

  n ≤ 1 ==> rad n = 1

lemma rad_max:

  1 < n ==> rad nn

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

Properties about squarefree

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