Theory Arith_Prog_Rel_Primes

(*
  File:   Arith_Prog_Rel_Primes.thy
  Author: Jose Manuel Rodriguez Caballero, University of Tartu
*)
section ‹Problem ARITHMETIC PROGRESSIONS (Putnam exam problems 2002)›
theory Arith_Prog_Rel_Primes
  imports
    Complex_Main 
    "HOL-Number_Theory.Number_Theory"
begin

text ‹
 Statement of the problem (from ~cite"putnam"): For which integers $n>1$ does the set of positive 
 integers less than and relatively prime to $n$ constitute an arithmetic progression?
 
 The solution of the above problem is theorem @{text arith_prog_rel_primes_solution}.

 First, we will require some auxiliary material before we get started with the actual
 solution.
›

subsection ‹Auxiliary results›

lemma even_and_odd_parts:
  fixes n::nat
  assumes n  0
  shows  k q::nat. n = (2::nat)^k*q  odd q
proof-
  have prime (2::nat)
    by simp    
  thus ?thesis
    using prime_power_canonical[where p = "2" and m = "n"]
      assms semiring_normalization_rules(7) by auto    
qed

lemma only_one_odd_div_power2:
  fixes n::nat
  assumes n  0 and   x. x dvd n  odd x  x = 1
  shows  k. n = (2::nat)^k
  by (metis even_and_odd_parts assms(1) assms(2) dvd_triv_left semiring_normalization_rules(11)
      semiring_normalization_rules(7))

lemma coprime_power2:
  fixes n::nat
  assumes n  0 and  x. x < n  (coprime x n  odd x)
  shows  k. n = (2::nat)^k
proof-
  have x dvd n  odd x  x = 1
    for x
    by (metis neq0_conv One_nat_def Suc_1 Suc_lessI assms(1) assms(2) coprime_left_2_iff_odd
        dvd_refl linorder_neqE_nat nat_dvd_1_iff_1 nat_dvd_not_less not_coprimeI)
  thus ?thesis
    using assms(1) only_one_odd_div_power2 
    by auto 
qed

subsection ‹Main result›

text ‹
  The solution to the problem  ARITHMETIC PROGRESSIONS (Putnam exam problems 2002)
›

theorem arith_prog_rel_primes_solution:
  fixes n :: nat
  assumes n > 1
  shows (prime n  ( k. n = 2^k)  n = 6)   
( a b m. m  0  {x | x. x < n  coprime x n} = {a+j*b| j::nat. j < m})
proof-
  have (prime n  ( k. n = 2^k)   n = 6) 
 ( b m. m  0  {x | x :: nat. x < n  coprime x n} = {1+j*b| j::nat. j < m})
  proof
    show "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
      if "prime n  (k. n = 2 ^ k)  n = 6"
    proof-
      have "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
        if "prime n"
      proof-
        have m.   m  0  {x | x :: nat. x < n  coprime x n} = {1+j| j::nat. j < m}
        proof-
          have {x | x :: nat. x < n  coprime x n} =  {x | x :: nat. x  0  x < n} 
          proof
            show "{x |x. x < n  coprime x n}  {x |x. x  0  x < n}"
              using prime_nat_iff'' that by fastforce
            show "{x |x. x  0  x < n}  {x |x. x < n  coprime x n}"
              using coprime_commute prime_nat_iff'' that 
              by fastforce              
          qed
          obtain m where m+1 = n
            using add.commute assms less_imp_add_positive by blast
          have {1+j| j::nat. j < (m::nat)} =  {x | x :: nat. x  0  x < m+1} 
            by (metis Suc_eq_plus1   m + 1 = n gr0_implies_Suc le_simps(3)   less_nat_zero_code   linorder_not_less nat.simps(3) nat_neq_iff  plus_1_eq_Suc )
          hence  {x | x :: nat. x < n  coprime x n} = {1+j| j::nat. j < (m::nat)}
            using {x | x :: nat. x < n  coprime x n} =  {x | x :: nat. x  0  x < n}  m+1 = n 
            by auto
          from n > 1 have m  0 
            using m + 1 = n by linarith
          have {x | x :: nat. x < n  coprime x n} = {1+j| j::nat. j < m} 
            using Suc_eq_plus1 1 < n {x |x. x < n  coprime x n} = {1 + j |j. j < m} 
            by auto
          hence ( m.  m  0  {x | x :: nat. x < n  coprime x n} = {1+j| j::nat. j < m})
            using m  0 
            by blast
          thus ?thesis by blast
        qed
        hence m.  m  0  {x | x :: nat. x < n  coprime x n} = {1+j*1| j::nat. j < m}
          by auto
        thus ?thesis
          by blast 
      qed
      moreover have "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
        if "k. n = 2 ^ k"
      proof-
        obtain k where n = 2 ^ k
          using k. n = 2 ^ k by auto
        have k  0 
          by (metis 1 < n n = 2 ^ k nat_less_le power.simps(1))
        obtain t where Suc t = k 
          by (metis k  0 fib.cases)
        have n = 2^(Suc t) 
          by (simp add: Suc t = k n = 2 ^ k)
        have {x | x :: nat. x < n  coprime x n} = {1+j*2| j::nat. j < 2^t}
        proof
          show "{x |x. x < n  coprime x n}  {1 + j * 2 |j. j < 2^t}"
          proof
            fix x
            assume x  {x |x. x < n  coprime x n}
            hence x < n
              by blast
            have coprime x n
              using x  {x |x. x < n  coprime x n}
              by blast
            hence coprime x (2^(Suc k))
              by (simp add: k  0 n = 2 ^ k)              
            have odd x
              using coprime x n k  0 n = 2 ^ k 
              by auto 
            then obtain j where x = 1+j*2
              by (metis add.commute add.left_commute left_add_twice mult_2_right oddE)
            have x < 2^k
              using n = 2 ^ k x < n x = 1+j*2 
              by linarith
            hence 1+j*2 < 2^k
              using x = 1+j*2
              by blast
            hence j < 2^t
              using Suc t = k by auto              
            thus x  {1 + j * 2 |j. j < 2^t}
              using x = 1+j*2
              by blast
          qed
          show "{1 + j * 2 |j. j < 2 ^ t}  {x |x. x < n  coprime x n}"
          proof
            fix x::nat
            assume x  {1 + j * 2 |j. j < 2 ^ t}
            then obtain j where x = 1 + j * 2 and j < 2 ^ t
              by blast
            have x < 2*(2^t)
              using  x = 1 + j * 2  j < 2 ^ t
              by linarith              
            hence x < n
              by (simp add: n = 2 ^ Suc t)
            moreover have coprime x n
              by (metis (no_types) thesis. (j. x = 1 + j * 2; j < 2 ^ t  thesis)  thesis n = 2 ^ k coprime_Suc_left_nat coprime_mult_right_iff coprime_power_right_iff plus_1_eq_Suc)              
            ultimately show x  {x |x. x < n  coprime x n}
              by blast
          qed
        qed
        have (2::nat)^(t::nat)  0 
          by simp
        obtain m where m = (2::nat)^t by blast
        have m  0 
          using m = 2 ^ t 
          by auto
        have {x | x :: nat. x < n  coprime x n} = {1+j*2| j::nat. j < m}
          using m = 2 ^ t {x |x. x < n  coprime x n} = {1 + j * 2 |j. j < 2 ^ t} 
          by auto
        from  m  0  {x | x :: nat. x < n  coprime x n} = {1+j*2| j::nat. j < m}
        show ?thesis by blast
      qed
      moreover have "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
        if "n = 6"
      proof-
        have  {x | x. x < 6  coprime x 6} = {1+j*4| j::nat. j < 2}
        proof-
          have {x | x::nat. x < 6  coprime x 6} = {1, 5}
          proof
            show "{u. x. u = (x::nat)  x < 6  coprime x 6}  {1, 5}"
            proof
              fix u::nat
              assume u  {u. x. u = x  x < 6  coprime x 6}
              hence coprime u 6
                by blast
              have u < 6
                using u  {u. x. u = x  x < 6  coprime x 6}
                by blast
              moreover have u  0
                using coprime u 6 ord_eq_0 
                by fastforce
              moreover have u  2
                using coprime u 6
                by auto
              moreover have u  3
              proof-
                have gcd (3::nat) 6 = 3
                  by auto
                thus ?thesis 
                  by (metis (no_types) coprime u 6 gcd 3 6 = 3 coprime_iff_gcd_eq_1 
                      numeral_eq_one_iff semiring_norm(86))
              qed
              moreover have u  4
              proof-
                have gcd (4::nat) 6 = 2
                  by (metis (no_types, lifting) add_numeral_left gcd_add1 gcd_add2 gcd_nat.idem
                      numeral_Bit0 numeral_One one_plus_numeral semiring_norm(4) semiring_norm(5))
                thus ?thesis
                  using coprime u 6 coprime_iff_gcd_eq_1 
                  by auto 
              qed
              ultimately have u = 1  u = 5
                by auto
              thus u  {1, 5}
                by blast
            qed
            show "{1::nat, 5}  {x |x. x < 6  coprime x 6}"
            proof-
              have (1::nat)  {x |x. x < 6  coprime x 6}
                by simp                
              moreover have (5::nat)  {x |x. x < 6  coprime x 6}
                by (metis Suc_numeral coprime_Suc_right_nat less_add_one mem_Collect_eq
                    numeral_plus_one semiring_norm(5) semiring_norm(8))                
              ultimately show ?thesis 
                by blast
            qed
          qed
          moreover have {1+j*4| j::nat. j < 2} = {1, 5}
            by auto
          ultimately show ?thesis by auto
        qed
        moreover have (2::nat)  0
          by simp          
        ultimately have  m.  m  0  {x | x :: nat. x < 6  coprime x 6} = {1+j*4| j::nat. j < m}
          by blast
        thus ?thesis
          using that 
          by auto 
      qed
      ultimately show ?thesis
        using that 
        by blast 
    qed
    show "prime n  (k. n = 2 ^ k)  n = 6"
      if "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
    proof-
      obtain b m where m  0 and {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}
        using b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
        by auto
      show ?thesis
      proof(cases n = 2)
        case True
        thus ?thesis
          by auto 
      next
        case False
        have b  4
        proof(cases odd b)
          case True
          show ?thesis
          proof(rule classical)
            assume ¬(b  4)
            hence b > 4 
              using le_less_linear 
              by blast
            obtain m where m  0 
              and {x | x :: nat. x < n  coprime x n} = {1+j*b| j::nat. j < m}
              using m  0 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            have b  0 
              using 4 < b 
              by linarith
            have n = 2 + (m-1)*b 
            proof-
              have n-1  {x | x :: nat. x < n  coprime x n} 
                using 1 < n coprime_diff_one_left_nat 
                by auto
              have n-1  {1+j*b| j::nat. j < m} 
                using n - 1  {x |x. x < n  coprime x n} 
                  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              then obtain i::nat where n-1 = 1+i*b and i < m 
                by blast
              have i  m-1 
                using i < m 
                by linarith
              have 1 + (m-1)*b  {1+j*b| j::nat. j < m} 
                using m  0 
                by auto
              hence 1 + (m-1)*b  {x | x::nat. x < n  coprime x n} 
                using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              hence 1 + (m-1)*b < n 
                by blast
              hence 1 + (m-1)*b  n-1 
                by linarith
              hence 1 + (m-1)*b  1+i*b 
                using n - 1 = 1 + i * b 
                by linarith
              hence (m-1)*b  i*b 
                by linarith
              hence m-1  i 
                using b  0 
                by auto
              hence m-1 = i 
                using i  m - 1 le_antisym 
                by blast
              thus ?thesis 
                using m  0 n - 1 = 1 + i * b 
                by auto
            qed
            have m  2 
              using n = 2 + (m - 1)*b n  2 
              by auto
            hence 1+b  {1+j*b| j. j < m} 
              by fastforce
            hence  1+b  {x | x::nat. x < n  coprime x n}
              using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            hence coprime (1+b) n 
              by blast
            have (2::nat) dvd (1+b) 
              using odd b 
              by simp
            hence coprime (2::nat) n 
              using coprime (1 + b) n coprime_common_divisor coprime_left_2_iff_odd odd_one 
              by blast
            have (2::nat) < n 
              using 1 < n n  2 
              by linarith
            have 2  {x | x :: nat. x < n  coprime x n} 
              using 2 < n coprime 2 n 
              by blast 
            hence  2  {1+j*b| j::nat. j < m} 
              using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            then obtain j::nat where 2 = 1+j*b 
              by blast 
            have  1 = j*b 
              using 2 = 1+j*b
              by linarith
            thus ?thesis 
              by simp
          qed
        next
          case False
          hence even b
            by simp
          show ?thesis
          proof(rule classical)
            assume ¬(b  4)
            hence b > 4 
              using le_less_linear 
              by blast
            obtain m where  m  0
              and {x | x::nat. x < n  coprime x n} = {1+j*b| j::nat. j < m}
              using m  0 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            have b  0 
              using 4 < b 
              by linarith
            have n = 2 + (m-1)*b 
            proof-
              have n-1  {x | x::nat. x < n  coprime x n} 
                using 1 < n coprime_diff_one_left_nat 
                by auto
              have n-1  {1+j*b| j::nat. j < m} 
                using n - 1  {x |x. x < n  coprime x n} 
                  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              then obtain i::nat where n-1 = 1+i*b and i < m 
                by blast
              have i  m-1 
                using i < m 
                by linarith
              have 1 + (m-1)*b  {1+j*b| j::nat. j < m} 
                using m  0 
                by auto
              hence 1 + (m-1)*b  {x | x :: nat. x < n  coprime x n} 
                using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              hence 1 + (m-1)*b < n 
                by blast
              hence 1 + (m-1)*b  n-1 
                by linarith
              hence 1 + (m-1)*b  1+i*b 
                using n - 1 = 1 + i * b 
                by linarith
              hence (m-1)*b  i*b 
                by linarith
              hence m-1  i 
                using b  0 
                by auto
              hence m-1 = i 
                using i  m - 1 le_antisym 
                by blast
              thus ?thesis 
                using m  0 n - 1 = 1 + i * b 
                by auto
            qed
            obtain k :: nat where b = 2*k 
              using even b
              by blast
            have n = 2*(1 + (m-1)*k)
              using  n = 2 + (m-1)*b  b = 2*k 
              by simp
            show ?thesis
            proof (cases odd m)
              case True
              hence odd m by blast
              then obtain t::nat where m-1 = 2*t 
                by (metis odd_two_times_div_two_nat)
              have  n = 2*(1 + b*t) 
                using m - 1 = 2 * t n = 2 + (m - 1) * b 
                by auto
              have t < m 
                using m - 1 = 2 * t m  0 
                by linarith
              have 1 + b*t  {1+j*b| j::nat. j < m} 
                using t < m 
                by auto 
              hence 1 + b*t  {x | x::nat. x < n  coprime x n} 
                using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast 
              hence coprime (1 + b*t) n 
                by auto
              thus ?thesis 
                by (metis (no_types, lifting) b = 2 * k n = 2 * (1 + (m - 1) * k) n = 2 * (1 + b * t) n = 2 + (m - 1) * b n  2 add_cancel_right_right coprime_mult_right_iff coprime_self mult_cancel_left mult_is_0 nat_dvd_1_iff_1)
            next
              case False
              thus ?thesis
              proof(cases odd k)
                case True
                hence odd k
                  by blast
                have even (1 + (m - 1) * k) 
                  by (simp add: False True m  0)
                have coprime (2 + (m - 1) * k) (1 + (m - 1) * k) 
                  by simp
                have coprime (2 + (m - 1) * k) n 
                  using coprime (2 + (m - 1) * k) (1 + (m - 1) * k) even (1 + (m - 1) * k) 
                    n = 2 * (1 + (m - 1) * k) coprime_common_divisor coprime_mult_right_iff
                    coprime_right_2_iff_odd odd_one 
                  by blast
                have 2 + (m - 1) * k < n 
                  by (metis (no_types, lifting) even (1 + (m - 1) * k) n = 2 * (1 + (m - 1) * k)
                      add_gr_0 add_mono_thms_linordered_semiring(1) dvd_add_left_iff dvd_add_triv_left_iff dvd_imp_le le_add2 le_neq_implies_less less_numeral_extra(1) mult_2 odd_one)
                have 2 + (m - 1) * k   {x | x :: nat. x < n  coprime x n} 
                  using 2 + (m - 1) * k < n coprime (2 + (m - 1) * k) n 
                  by blast
                hence 2 + (m - 1) * k   {1 + j * b |j. j < m} 
                  using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                  by blast
                then obtain j::nat where  2 + (m - 1) * k  = 1 + j * b and j < m
                  by blast
                have  1 + (m - 1) * k  = j * b
                  using 2 + (m - 1) * k  = 1 + j * b
                  by simp
                hence  1 + (m - 1) * k  = j * (2*k) 
                  using b = 2 * k by blast
                thus ?thesis 
                  by (metis b = 2 * k even b n = 2 * (1 + (m - 1) * k) n = 2 + (m - 1) * b dvd_add_times_triv_right_iff dvd_antisym dvd_imp_le dvd_triv_right even_numeral mult_2 zero_less_numeral)
              next
                case False
                hence even k by auto
                have odd (1 + (m - 1) * k) 
                  by (simp add: even k )
                hence coprime (3 + (m - 1) * k) (1 + (m - 1) * k) 
                  by (smt (verit) add_numeral_left coprime_common_divisor coprime_right_2_iff_odd dvd_add_left_iff not_coprimeE numeral_Bit1 numeral_One numeral_plus_one one_add_one)
                hence coprime (3 + (m - 1) * k) n 
                  by (metis even k n = 2 * (1 + (m - 1) * k) coprime_mult_right_iff coprime_right_2_iff_odd even_add even_mult_iff odd_numeral)
                have 3 + (m - 1) * k < n 
                  by (smt (verit) Groups.add_ac(2) even k n = 2 * (1 + (m - 1) * k) n = 2 + (m - 1) * b n  2 add_Suc_right add_cancel_right_right add_mono_thms_linordered_semiring(1) dvd_imp_le even_add even_mult_iff le_add2 le_neq_implies_less left_add_twice mult_2 neq0_conv numeral_Bit1 numeral_One odd_numeral one_add_one plus_1_eq_Suc)
                have 3 + (m - 1) * k  {x |x. x < n  coprime x n} 
                  using 3 + (m - 1) * k < n coprime (3 + (m - 1) * k) n 
                  by blast
                hence 3 + (m - 1) * k  {1 + j * b |j. j < m} 
                  using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                  by blast 
                then obtain j::nat where 3 + (m - 1) * k = 1 + j * b 
                  by blast  
                have 2 + (m - 1) * k = j * b 
                  using 3 + (m - 1) * k = 1 + j * b 
                  by simp
                hence  2 + (m - 1) * k = j * 2*k 
                  by (simp add: b = 2 * k)
                thus ?thesis 
                  by (metis 4 < b b = 2 * k even k dvd_add_times_triv_right_iff dvd_antisym 
                      dvd_triv_right mult_2 nat_neq_iff numeral_Bit0)
              qed
            qed
          qed
        qed
        moreover have b  3
        proof (rule classical)
          assume ¬ (b  3)
          hence b = 3 
            by blast
          obtain m where  m  0 and 
            {x | x::nat. x < n  coprime x n} = {1+j*b| j::nat. j < m}
            using m  0 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
            by blast
          have b  0 
            by (simp add: b = 3)
          have n = 2 + (m-1)*b 
          proof-
            have n-1  {x | x::nat. x < n  coprime x n} 
              using 1 < n coprime_diff_one_left_nat 
              by auto
            have n-1  {1+j*b| j::nat. j < m} 
              using n - 1  {x |x. x < n  coprime x n} 
                {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            then obtain i::nat where n-1 = 1+i*b and i < m 
              by blast
            have i  m-1 
              using i < m 
              by linarith
            have 1 + (m-1)*b  {1+j*b| j::nat. j < m} 
              using m  0 
              by auto
            hence 1 + (m-1)*b  {x | x :: nat. x < n  coprime x n} 
              using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            hence 1 + (m-1)*b < n 
              by blast
            hence 1 + (m-1)*b  n-1 
              by linarith
            hence 1 + (m-1)*b  1+i*b 
              using n - 1 = 1 + i * b 
              by linarith
            hence (m-1)*b  i*b 
              by linarith
            hence m-1  i 
              using b  0 
              by auto
            hence m-1 = i 
              using i  m - 1 le_antisym 
              by blast
            thus ?thesis 
              using m  0 n - 1 = 1 + i * b 
              by auto
          qed
          have n > 2 
            using 1 < n n  2 
            by linarith
          hence m  2 using  n = 2 + (m-1)*b b = 3 
            by simp
          have 4  {1+j*(b::nat)| j::nat. j < m} 
            using 2  m b = 3 
            by force
          hence (4::nat)   {x | x :: nat. x < n  coprime x n} 
            using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}
            by auto
          hence coprime (4::nat) n 
            by blast
          have (2::nat) dvd 4 
            by auto
          hence coprime (2::nat) n 
            using coprime (4::nat) n coprime_divisors dvd_refl 
            by blast
          have 4 < n 
            using 4  {x |x. x < n  coprime x n} 
            by blast
          have 2 < (4::nat) 
            by auto
          have  2 < n 
            by (simp add: 2 < n)
          hence 2  {x | x :: nat. x < n  coprime x n} 
            using  coprime (2::nat) n 
            by blast
          hence  2  {1+j*(b::nat)| j::nat. j < m} 
            using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
            by blast
          then obtain j::nat where 2 = 1+j*3 
            using b = 3 
            by blast
          from  2 = 1+j*3
          have  1 = j*3 
            by auto
          hence 3 dvd 1 
            by auto
          thus ?thesis
            using nat_dvd_1_iff_1 numeral_eq_one_iff 
            by blast
        qed
        ultimately have b = 0  b = 1  b = 2  b = 4
          by auto
        moreover have b = 0  k. n = 2^k
        proof-
          assume b = 0
          have {1 + j * b |j. j < m} = {1}
            using b = 0 m  0 
            by auto
          hence {x |x. x < n  coprime x n} = {1}
            using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}
            by blast
          hence n = 2
          proof-
            have n-1   {x | x :: nat. x < n  coprime x n} 
              using 1 < n coprime_diff_one_left_nat 
              by auto
            have n-1  {1} 
              using n - 1  {x |x. x < n  coprime x n} {x |x. x < n  coprime x n} = {1} 
              by blast
            hence n-1 = 1 
              by blast
            hence n = 2 
              by simp
            thus ?thesis 
              by blast
          qed
          hence n = 2^1
            by auto
          thus ?thesis
            by blast 
        qed
        moreover have b = 1  prime n
        proof-
          assume b = 1
          have x < n  x  0  coprime x n
            for x
          proof-
            assume x < n and x  0
            have {1+j| j::nat. j < m} = {x | x::nat. x < m+1  x  0} 
              by (metis (full_types) Suc_eq_plus1  add_mono1 less_Suc_eq_0_disj  nat.simps(3) plus_1_eq_Suc )
            hence {x | x :: nat. x < n  coprime x n} = {x | x :: nat. x < m+1  x  0}
              using b = 1 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by auto
            have coprime (n-1) n 
              using 1 < n coprime_diff_one_left_nat 
              by auto
            have n-1 < n 
              using 1 < n 
              by auto
            have n-1  {x |x. x < n  coprime x n} 
              using coprime (n - 1) n n - 1 < n 
              by blast
            have n-1  m 
              by (metis (no_types, lifting) CollectD Suc_eq_plus1 Suc_less_eq2 n - 1  {x |x. x < n  coprime x n} {x |x. x < n  coprime x n} = {x |x. x < m + 1  x  0}   leD  le_less_linear not_less_eq_eq )
            have m   {x | x :: nat. x < m+1  x  0} 
              using m  0 
              by auto
            have m  {x |x. x < n  coprime x n} 
              using m  {x |x. x < m + 1  x  0} 
                {x |x. x < n  coprime x n} = {x |x. x < m + 1  x  0} 
              by blast
            have m < n 
              using m  {x |x. x < n  coprime x n} 
              by blast
            have m+1 = n 
              using m < n n - 1  m 
              by linarith
            have x   {x | x :: nat. x < m+1  x  0} 
              using m + 1 = n x < n x  0 
              by blast
            hence x  {x |x. x < n  coprime x n} 
              using {x |x. x < n  coprime x n} = {x |x. x < m + 1  x  0} 
              by blast
            thus ?thesis 
              by blast
          qed
          thus ?thesis
            using assms coprime_commute nat_neq_iff prime_nat_iff'' by auto 
        qed
        moreover have b = 2   k. n = 2^k
        proof-
          assume b = 2
          have {x | x :: nat. x < n  coprime x n} = {1+j*2| j::nat. j < m}
            using b = 2 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
            by auto
          have x < n  coprime x n  odd x
            for x::nat
          proof-
            assume x < n
            have coprime x n  odd x
            proof-
              assume coprime x n
              have x  {x | x :: nat. x < n  coprime x n} 
                by (simp add: coprime x n x < n)
              hence x  {1+j*2| j::nat. j < m} 
                using {x |x. x < n  coprime x n} = {1 + j * 2 |j. j < m} 
                by blast
              then obtain j where x = 1+j*2 
                by blast
              thus ?thesis
                by simp
            qed
            moreover have odd x  coprime x n
            proof-
              assume odd x
              obtain j::nat where x = 1+j*2 
                by (metis odd x add.commute mult_2_right odd_two_times_div_two_succ one_add_one semiring_normalization_rules(16)) 
              have j < (n-1)/2 
                using x < n x = 1 + j * 2 
                by linarith
              have n = 2*m
              proof-
                have  (2::nat)  0 
                  by auto
                have n = 2+(m-1)*2 
                proof-
                  have n-1  {x | x :: nat. x < n  coprime x n} 
                    using 1 < n coprime_diff_one_left_nat 
                    by auto
                  have n-1  {1+j*b| j::nat. j < m} 
                    using n - 1  {x |x. x < n  coprime x n} 
                      {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                    by blast
                  then obtain i::nat where n-1 = 1+i*b and i < m 
                    by blast
                  have i  m-1 
                    using i < m 
                    by linarith
                  have 1 + (m-1)*b  {1+j*b| j::nat. j < m} 
                    using m  0 by auto
                  hence 1 + (m-1)*b  {x | x :: nat. x < n  coprime x n} 
                    using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                    by blast
                  hence 1 + (m-1)*b < n 
                    by blast
                  hence 1 + (m-1)*b  n-1 
                    by linarith
                  hence 1 + (m-1)*b  1+i*b 
                    using n - 1 = 1 + i * b 
                    by linarith
                  hence (m-1)*b  i*b 
                    by linarith
                  hence m-1  i 
                  proof-
                    have b  0
                      using b = 2
                      by simp
                    thus ?thesis
                      using (m - 1) * b  i * b mult_le_cancel2 
                      by blast 
                  qed
                  hence m-1 = i 
                    using i  m - 1 le_antisym 
                    by blast
                  thus ?thesis 
                    using m  0 n - 1 = 1 + i * b
                    by (simp add: b = 2)
                qed
                thus  ?thesis 
                  by (simp add: m  0 n = 2 + (m - 1) * 2 mult.commute mult_eq_if)
              qed
              hence j < m 
                using x < n x = 1 + j * 2 
                by linarith
              hence x  {1+j*2| j::nat. j < m} 
                using x = 1 + j * 2 
                by blast
              hence x  {x | x :: nat. x < n  coprime x n} 
                using {x |x. x < n  coprime x n} = {1 + j * 2 |j. j < m} 
                by blast
              thus ?thesis 
                by blast
            qed
            ultimately show ?thesis 
              by blast
          qed
          thus ?thesis 
            using coprime_power2 assms 
            by auto
        qed
        moreover have b = 4  n = 6
        proof-
          assume b = 4
          have n = 2  n = 6
          proof(rule classical)
            assume ¬ (n = 2  n = 6)
            have  (4::nat)  0 
              by auto
            have n =  2+(m-1)*4 
            proof-
              have n-1  {x | x :: nat. x < n  coprime x n} 
                using 1 < n coprime_diff_one_left_nat 
                by auto
              have n-1  {1+j*b| j::nat. j < m} 
                using n - 1  {x |x. x < n  coprime x n} 
                  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              then obtain i::nat where n-1 = 1+i*b and i < m 
                by blast
              have i  m-1 
                using i < m 
                by linarith
              have 1 + (m-1)*b  {1+j*b| j::nat. j < m} 
                using m  0 
                by auto
              hence 1 + (m-1)*b  {x | x :: nat. x < n  coprime x n} 
                using {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
                by blast
              hence 1 + (m-1)*b < n 
                by blast
              hence 1 + (m-1)*b  n-1 
                by linarith
              hence 1 + (m-1)*b  1+i*b 
                using n - 1 = 1 + i * b 
                by linarith
              hence (m-1)*b  i*b 
                by linarith
              hence m-1  i 
              proof-
                have b  0
                  using b = 4 by auto
                thus ?thesis
                  using (m - 1) * b  i * b mult_le_cancel2 
                  by blast 
              qed
              hence m-1 = i 
                using i  m - 1 le_antisym 
                by blast
              thus ?thesis 
                using m  0 n - 1 = 1 + i * b
                by (simp add: b = 4) 
            qed
            hence n = 4*m - 2 
              by (simp add: m  0 mult.commute mult_eq_if)
            have m  3 
              using ¬ (n = 2  n = 6) n = 2 + (m - 1) * 4 
              by auto
            hence {1+j*4| j::nat. j < 3}  {1+j*4| j::nat. j < m}
              by force
            hence 9  {1+j*4| j::nat. j < 3} 
              by force
            hence 9  {1+j*4| j::nat. j < m} 
              using  {1+j*4| j::nat. j < 3}  {1+j*4| j::nat. j < m} 
              by blast
            hence 9  {x | x :: nat. x < n  coprime x n}
              using b = 4 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by auto
            hence coprime (9::nat) n 
              by blast
            have (3::nat) dvd 9 
              by auto
            have  coprime (3::nat) n using  coprime (9::nat) n (3::nat) dvd 9
              by (metis coprime_commute coprime_mult_right_iff dvd_def)
            have (3::nat) < n 
              by (metis One_nat_def Suc_lessI 1 < n ¬ (n = 2  n = 6) coprime 3 n
                  coprime_self numeral_2_eq_2 numeral_3_eq_3 less_numeral_extra(1) nat_dvd_not_less)
            have 3   {x | x :: nat. x < n  coprime x n} 
              using 3 < n coprime 3 n 
              by blast
            hence  (3::nat)  {1+j*4| j::nat. j < m}
              using b = 4 {x |x. x < n  coprime x n} = {1 + j * b |j. j < m} 
              by blast
            then obtain j::nat where (3::nat) = 1 + j*4 
              by blast  
            have 2 = j*4 
              using numeral_3_eq_3 (3::nat) = 1 + j*4
              by linarith
            hence 1 = j*2 
              by linarith
            hence even 1 
              by simp
            thus ?thesis 
              using odd_one 
              by blast
          qed
          thus ?thesis
            by (simp add: False)            
        qed
        ultimately show ?thesis 
          by blast
      qed
    qed
  qed
  moreover have ( b m. m  0  {x | x :: nat. x < n  coprime x n} = {1+j*b| j::nat. j < m})
   ( a b m. m  0  {x | x :: nat. x < n  coprime x n} = {a+j*b| j::nat. j < m})
  proof
    show "a b m. m  0  {x |x. x < n  coprime x n} = {a + j * b |j. j < m}"
      if "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
      using that
      by blast 
    show "b m. m  0  {x |x. x < n  coprime x n} = {1 + j * b |j. j < m}"
      if "a b m. m  0  {x |x. x < n  coprime x n} = {a + j * b |j. j < m}"
    proof-
      obtain a b m::nat where m  0
        and {x | x :: nat. x < n  coprime x n} = {a+j*b| j::nat. j < m}
        using a b m. m  0  {x |x. x < n  coprime x n} = {a + j * b |j. j < m} 
        by auto        
      have a = 1 
      proof-
        have {x | x :: nat. x < n  coprime x n} = {(a::nat)+j*(b::nat)| j::nat. j < m}  a = 1
        proof-
          have Min {x | x :: nat. x < n  coprime x n} = Min {a+j*b| j::nat. j < m}
            using {x |x. x < n  coprime x n} = {a + j * b |j. j < m} 
            by auto            
          have  Min {x | x :: nat. x < n  coprime x n} = 1
          proof-
            have finite {x | x :: nat. x < n  coprime x n}
              by auto
            have {x | x :: nat. x < n  coprime x n}  {} 
              using 1 < n by auto
            have 1  {x | x :: nat. x < n  coprime x n} 
              using 1 < n 
              by auto
            have  x. coprime x n  x  1 
              using 1 < n le_less_linear 
              by fastforce
            hence  x.  x < n  coprime x n  x  1 
              by blast
            hence  x  {x | x :: nat. x < n  coprime x n}. x  1 
              by blast
            hence Min {x | x :: nat. x < n  coprime x n}  1 
              using finite {x | x :: nat. x < n  coprime x n} {x |x. x < n  coprime x n}  {}
              by auto
            thus ?thesis 
              using Min_le 1  {x |x. x < n  coprime x n} finite {x |x. x < n  coprime x n}
                antisym by blast
          qed
          have Min  {a+j*b| j::nat. j < m} = a
          proof -
            have f1: "n. a = a + n * b  n < m"
              using m  0 
              by auto
            have f2: "n. 1 = a + n * b  n < m"
              using {x |x. x < n  coprime x n} = {a + j * b |j. j < m} assms coprime_1_left 
              by blast
            have f3: "na. a = na  na < n  coprime na n"
              using f1 {x |x. x < n  coprime x n} = {a + j * b |j. j < m} by blast
            have "n  1"
              by (metis (lifting) assms less_irrefl_nat)
            then have "¬ coprime 0 n"
              by simp
            then show ?thesis
              using f3 f2 by (metis Min {x |x. x < n  coprime x n} = 1 {x |x. x < n  coprime x n} = {a + j * b |j. j < m} less_one linorder_neqE_nat not_add_less1)
          qed
          hence Min  {a+j*b| j::nat. j < m} = a by blast
          thus ?thesis 
            using Min {x | x :: nat. x < n  coprime x n} = 1 Min {x | x :: nat. x < n  coprime x n} = Min {a+j*b| j::nat. j < m}
            by linarith
        qed
        thus ?thesis
          using {x |x. x < n  coprime x n} = {a + j * b |j. j < m} 
          by blast 
      qed
      thus ?thesis using  m  0 {x | x. x < n  coprime x n} = {a+j*b| j::nat. j < m} 
        by auto
    qed
  qed 
  ultimately show ?thesis
    by simp 
qed

end