[GOAL]
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
⊢ coprime n b
[PROOFSTEP]
by_cases h₃ : 2 ≤ n
[GOAL]
case pos
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
h₃ : 2 ≤ n
⊢ coprime n b
[PROOFSTEP]
apply Nat.coprime_of_dvd
[GOAL]
case pos.H
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
h₃ : 2 ≤ n
⊢ ∀ (k : ℕ), Prime k → k ∣ n → ¬k ∣ b
[PROOFSTEP]
rintro k hk ⟨m, rfl⟩
  ⟨j, rfl⟩
      -- Because prime numbers do not divide 1, it suffices to show that `k ∣ 1` to prove a
          -- contradiction
[GOAL]
case pos.H.intro.intro
k : ℕ
hk : Prime k
m : ℕ
h₁ : 1 ≤ k * m
h₃ : 2 ≤ k * m
j : ℕ
h₂ : 1 ≤ k * j
h : ProbablePrime (k * m) (k * j)
⊢ False
[PROOFSTEP]
apply Nat.Prime.not_dvd_one hk
[GOAL]
case pos.H.intro.intro
k : ℕ
hk : Prime k
m : ℕ
h₁ : 1 ≤ k * m
h₃ : 2 ≤ k * m
j : ℕ
h₂ : 1 ≤ k * j
h : ProbablePrime (k * m) (k * j)
⊢ k ∣ 1
[PROOFSTEP]
replace h := dvd_of_mul_right_dvd h
[GOAL]
case pos.H.intro.intro
k : ℕ
hk : Prime k
m : ℕ
h₁ : 1 ≤ k * m
h₃ : 2 ≤ k * m
j : ℕ
h₂ : 1 ≤ k * j
h : k ∣ (k * j) ^ (k * m - 1) - 1
⊢ k ∣ 1
[PROOFSTEP]
rw [Nat.dvd_add_iff_right h, Nat.sub_add_cancel (Nat.one_le_pow _ _ h₂)]
  -- Since `k` divides `b`, `k` also divides any power of `b` except `b ^ 0`. Therefore, it
      -- suffices to show that `n - 1` isn't zero. However, we know that `n - 1` isn't zero because we
      -- assumed `2 ≤ n` when doing `by_cases`.
[GOAL]
case pos.H.intro.intro
k : ℕ
hk : Prime k
m : ℕ
h₁ : 1 ≤ k * m
h₃ : 2 ≤ k * m
j : ℕ
h₂ : 1 ≤ k * j
h : k ∣ (k * j) ^ (k * m - 1) - 1
⊢ k ∣ (k * j) ^ (k * m - 1)
[PROOFSTEP]
refine' dvd_of_mul_right_dvd (dvd_pow_self (k * j) _)
[GOAL]
case pos.H.intro.intro
k : ℕ
hk : Prime k
m : ℕ
h₁ : 1 ≤ k * m
h₃ : 2 ≤ k * m
j : ℕ
h₂ : 1 ≤ k * j
h : k ∣ (k * j) ^ (k * m - 1) - 1
⊢ k * m - 1 ≠ 0
[PROOFSTEP]
linarith [tsub_pos_of_lt (one_lt_two.trans_le h₃)]
  -- If `n = 1`, then it follows trivially that `n` is coprime with `b`.
[GOAL]
case neg
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
h₃ : ¬2 ≤ n
⊢ coprime n b
[PROOFSTEP]
rw [show n = 1 by linarith]
[GOAL]
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
h₃ : ¬2 ≤ n
⊢ n = 1
[PROOFSTEP]
linarith
[GOAL]
case neg
n b : ℕ
h : ProbablePrime n b
h₁ : 1 ≤ n
h₂ : 1 ≤ b
h₃ : ¬2 ≤ n
⊢ coprime 1 b
[PROOFSTEP]
norm_num
[GOAL]
n b : ℕ
h : 1 ≤ b
⊢ ProbablePrime n b ↔ b ^ (n - 1) ≡ 1 [MOD n]
[PROOFSTEP]
have : 1 ≤ b ^ (n - 1) :=
  one_le_pow_of_one_le h
    (n - 1)
      -- For exact_mod_cast
[GOAL]
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
⊢ ProbablePrime n b ↔ b ^ (n - 1) ≡ 1 [MOD n]
[PROOFSTEP]
rw [Nat.ModEq.comm]
[GOAL]
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
⊢ ProbablePrime n b ↔ 1 ≡ b ^ (n - 1) [MOD n]
[PROOFSTEP]
constructor
[GOAL]
case mp
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
⊢ ProbablePrime n b → 1 ≡ b ^ (n - 1) [MOD n]
[PROOFSTEP]
intro h₁
[GOAL]
case mp
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
h₁ : ProbablePrime n b
⊢ 1 ≡ b ^ (n - 1) [MOD n]
[PROOFSTEP]
apply Nat.modEq_of_dvd
[GOAL]
case mp.a
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
h₁ : ProbablePrime n b
⊢ ↑n ∣ ↑(b ^ (n - 1)) - ↑1
[PROOFSTEP]
exact_mod_cast h₁
[GOAL]
case mpr
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
⊢ 1 ≡ b ^ (n - 1) [MOD n] → ProbablePrime n b
[PROOFSTEP]
intro h₁
[GOAL]
case mpr
n b : ℕ
h : 1 ≤ b
this : 1 ≤ b ^ (n - 1)
h₁ : 1 ≡ b ^ (n - 1) [MOD n]
⊢ ProbablePrime n b
[PROOFSTEP]
exact_mod_cast Nat.ModEq.dvd h₁
[GOAL]
n b : ℕ
h : FermatPsp n b
h₁ : 1 ≤ b
⊢ coprime n b
[PROOFSTEP]
rcases h with ⟨hp, _, hn₂⟩
[GOAL]
case intro.intro
n b : ℕ
h₁ : 1 ≤ b
hp : ProbablePrime n b
left✝ : ¬Prime n
hn₂ : 1 < n
⊢ coprime n b
[PROOFSTEP]
exact coprime_of_probablePrime hp (by linarith) h₁
[GOAL]
n b : ℕ
h₁ : 1 ≤ b
hp : ProbablePrime n b
left✝ : ¬Prime n
hn₂ : 1 < n
⊢ 1 ≤ n
[PROOFSTEP]
linarith
[GOAL]
n : ℕ
h₁ : 1 < n
h₂ : ¬Prime n
⊢ FermatPsp n 1
[PROOFSTEP]
refine' ⟨show n ∣ 1 ^ (n - 1) - 1 from _, h₂, h₁⟩
[GOAL]
n : ℕ
h₁ : 1 < n
h₂ : ¬Prime n
⊢ n ∣ 1 ^ (n - 1) - 1
[PROOFSTEP]
exact show 0 = 1 ^ (n - 1) - 1 by norm_num ▸ dvd_zero n
[GOAL]
n : ℕ
h₁ : 1 < n
h₂ : ¬Prime n
⊢ 0 = 1 ^ (n - 1) - 1
[PROOFSTEP]
norm_num
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
⊢ 2 ≤ (a ^ b - 1) / (a - 1)
[PROOFSTEP]
change 1 < _
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
⊢ 1 < (a ^ b - 1) / (a - 1)
[PROOFSTEP]
have h₁ : a - 1 ∣ a ^ b - 1 := by simpa only [one_pow] using nat_sub_dvd_pow_sub_pow a 1 b
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
⊢ a - 1 ∣ a ^ b - 1
[PROOFSTEP]
simpa only [one_pow] using nat_sub_dvd_pow_sub_pow a 1 b
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
h₁ : a - 1 ∣ a ^ b - 1
⊢ 1 < (a ^ b - 1) / (a - 1)
[PROOFSTEP]
rw [Nat.lt_div_iff_mul_lt h₁, mul_one, tsub_lt_tsub_iff_right (Nat.le_of_succ_le ha)]
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
h₁ : a - 1 ∣ a ^ b - 1
⊢ a < a ^ b
[PROOFSTEP]
convert pow_lt_pow (Nat.lt_of_succ_le ha) hb
[GOAL]
case h.e'_3
a b : ℕ
ha : 2 ≤ a
hb : 2 ≤ b
h₁ : a - 1 ∣ a ^ b - 1
⊢ a = a ^ 1
[PROOFSTEP]
rw [pow_one]
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 < b
⊢ 2 ≤ (a ^ b + 1) / (a + 1)
[PROOFSTEP]
rw [Nat.le_div_iff_mul_le (Nat.zero_lt_succ _)]
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 < b
⊢ 2 * succ a ≤ a ^ b + 1
[PROOFSTEP]
apply Nat.succ_le_succ
[GOAL]
case a
a b : ℕ
ha : 2 ≤ a
hb : 2 < b
⊢ Nat.mul 2 a + 1 ≤ a ^ b
[PROOFSTEP]
calc
  2 * a + 1 ≤ a ^ 2 * a := by nlinarith
  _ = a ^ 3 := by rw [pow_succ a 2]
  _ ≤ a ^ b := pow_le_pow (Nat.le_of_succ_le ha) hb
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 < b
⊢ 2 * a + 1 ≤ a ^ 2 * a
[PROOFSTEP]
nlinarith
[GOAL]
a b : ℕ
ha : 2 ≤ a
hb : 2 < b
⊢ a ^ 2 * a = a ^ 3
[PROOFSTEP]
rw [pow_succ a 2]
[GOAL]
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
⊢ (b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1)) = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
have q₁ : b - 1 ∣ b ^ p - 1 := by simpa only [one_pow] using nat_sub_dvd_pow_sub_pow b 1 p
[GOAL]
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
⊢ b - 1 ∣ b ^ p - 1
[PROOFSTEP]
simpa only [one_pow] using nat_sub_dvd_pow_sub_pow b 1 p
[GOAL]
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
⊢ (b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1)) = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
have q₂ : b + 1 ∣ b ^ p + 1 := by simpa only [one_pow] using hp.nat_add_dvd_pow_add_pow b 1
[GOAL]
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
⊢ b + 1 ∣ b ^ p + 1
[PROOFSTEP]
simpa only [one_pow] using hp.nat_add_dvd_pow_add_pow b 1
[GOAL]
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
q₂ : b + 1 ∣ b ^ p + 1
⊢ (b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1)) = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
convert Nat.div_mul_div_comm q₁ q₂ using 2
[GOAL]
case h.e'_3.h.e'_5
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
q₂ : b + 1 ∣ b ^ p + 1
⊢ b ^ (2 * p) - 1 = (b ^ p - 1) * (b ^ p + 1)
[PROOFSTEP]
rw [mul_comm (_ - 1), ← Nat.sq_sub_sq]
[GOAL]
case h.e'_3.h.e'_6
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
q₂ : b + 1 ∣ b ^ p + 1
⊢ b ^ 2 - 1 = (b - 1) * (b + 1)
[PROOFSTEP]
rw [mul_comm (_ - 1), ← Nat.sq_sub_sq]
[GOAL]
case h.e'_3.h.e'_5
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
q₂ : b + 1 ∣ b ^ p + 1
⊢ b ^ (2 * p) - 1 = (b ^ p) ^ 2 - 1 ^ 2
[PROOFSTEP]
ring_nf
[GOAL]
case h.e'_3.h.e'_6
b p : ℕ
x✝ : 2 ≤ b
hp : Odd p
q₁ : b - 1 ∣ b ^ p - 1
q₂ : b + 1 ∣ b ^ p + 1
⊢ b ^ 2 - 1 = b ^ 2 - 1 ^ 2
[PROOFSTEP]
simp
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ b ^ (2 * p) - 1 - (b ^ 2 - 1) = b ^ (2 * p) - (1 + (b ^ 2 - 1))
[PROOFSTEP]
rw [Nat.sub_sub]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ b ^ (2 * p) - (1 + (b ^ 2 - 1)) = b ^ (2 * p) - (1 + b ^ 2 - 1)
[PROOFSTEP]
rw [Nat.add_sub_assoc hi_bsquared]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ b ^ (2 * p) - (1 + b ^ 2 - 1) = b ^ (2 * p) - b ^ 2
[PROOFSTEP]
rw [Nat.add_sub_cancel_left]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ b ^ (2 * p) - b ^ 2 = b ^ (p * 2) - b ^ 2
[PROOFSTEP]
rw [mul_comm]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ b ^ (p * 2) - b ^ 2 = (b ^ p) ^ 2 - b ^ 2
[PROOFSTEP]
rw [pow_mul]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b ^ p) ^ 2 - b ^ 2 = (b ^ p + b) * (b ^ p - b)
[PROOFSTEP]
rw [Nat.sq_sub_sq]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b ^ p + b) * (b ^ p - b) = (b ^ p - b) * (b ^ p + b)
[PROOFSTEP]
rw [mul_comm]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b ^ p - b) * (b ^ p + b) = (b ^ (p - 1 + 1) - b) * (b ^ p + b)
[PROOFSTEP]
rw [Nat.sub_add_cancel hp]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b ^ (p - 1 + 1) - b) * (b ^ p + b) = (b * b ^ (p - 1) - b) * (b ^ p + b)
[PROOFSTEP]
rw [pow_succ']
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b * b ^ (p - 1) - b) * (b ^ p + b) = (b * b ^ (p - 1) - b * 1) * (b ^ p + b)
[PROOFSTEP]
rw [mul_one]
[GOAL]
b p : ℕ
hb : 0 < b
hp : 1 ≤ p
hi_bsquared : 1 ≤ b ^ 2
⊢ (b * b ^ (p - 1) - b * 1) * (b ^ p + b) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
rw [Nat.mul_sub_left_distrib]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
⊢ FermatPsp (Nat.psp_from_prime b p) b
[PROOFSTEP]
unfold psp_from_prime
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
⊢ FermatPsp ((b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1))) b
[PROOFSTEP]
set A := (b ^ p - 1) / (b - 1)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
⊢ FermatPsp (A * ((b ^ p + 1) / (b + 1))) b
[PROOFSTEP]
set B :=
  (b ^ p + 1) /
    (b + 1)
      -- Inequalities
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_A : 1 < A := a_id_helper (Nat.succ_le_iff.mp b_ge_two) (Nat.Prime.one_lt p_prime)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_B : 1 < B := b_id_helper (Nat.succ_le_iff.mp b_ge_two) p_gt_two
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_AB : 1 < A * B := one_lt_mul'' hi_A hi_B
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_b : 0 < b := by linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
⊢ 0 < b
[PROOFSTEP]
linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_p : 1 ≤ p := Nat.one_le_of_lt p_gt_two
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_bsquared : 0 < b ^ 2 - 1 := by
  -- Porting note: was `by nlinarith [Nat.one_le_pow 2 b hi_b]`
  have h0 := mul_le_mul b_ge_two b_ge_two zero_le_two hi_b.le
  have h1 : 1 < 2 * 2 := by linarith
  have := tsub_pos_of_lt (h1.trans_le h0)
  rwa [pow_two]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
⊢ 0 < b ^ 2 - 1
[PROOFSTEP]
have h0 := mul_le_mul b_ge_two b_ge_two zero_le_two hi_b.le
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
h0 : 2 * 2 ≤ b * b
⊢ 0 < b ^ 2 - 1
[PROOFSTEP]
have h1 : 1 < 2 * 2 := by linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
h0 : 2 * 2 ≤ b * b
⊢ 1 < 2 * 2
[PROOFSTEP]
linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
h0 : 2 * 2 ≤ b * b
h1 : 1 < 2 * 2
⊢ 0 < b ^ 2 - 1
[PROOFSTEP]
have := tsub_pos_of_lt (h1.trans_le h0)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
h0 : 2 * 2 ≤ b * b
h1 : 1 < 2 * 2
this : 0 < b * b - 1
⊢ 0 < b ^ 2 - 1
[PROOFSTEP]
rwa [pow_two]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_bpowtwop : 1 ≤ b ^ (2 * p) := Nat.one_le_pow (2 * p) b hi_b
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hi_bpowpsubone : 1 ≤ b ^ (p - 1) := Nat.one_le_pow (p - 1) b hi_b
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have p_odd : Odd p := p_prime.odd_of_ne_two p_gt_two.ne.symm
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have AB_not_prime : ¬Nat.Prime (A * B) := Nat.not_prime_mul hi_A hi_B
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1) := AB_id_helper _ _ b_ge_two p_odd
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
⊢ FermatPsp (A * B) b
[PROOFSTEP]
have hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1 := by simpa only [one_pow, pow_mul] using nat_sub_dvd_pow_sub_pow _ 1 p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
⊢ b ^ 2 - 1 ∣ b ^ (2 * p) - 1
[PROOFSTEP]
simpa only [one_pow, pow_mul] using nat_sub_dvd_pow_sub_pow _ 1 p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ FermatPsp (A * B) b
[PROOFSTEP]
refine'
  ⟨_, AB_not_prime, hi_AB⟩
    -- Used to prove that `2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)`.
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b) :=
  by
  apply_fun fun x => x * (b ^ 2 - 1) at AB_id
  rw [Nat.div_mul_cancel hd] at AB_id
  apply_fun fun x => x - (b ^ 2 - 1) at AB_id
  nth_rw 2 [← one_mul (b ^ 2 - 1)] at AB_id
  rw [← Nat.mul_sub_right_distrib, mul_comm] at AB_id
  rw [AB_id]
  exact bp_helper hi_b hi_p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
apply_fun fun x => x * (b ^ 2 - 1) at AB_id
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : A * B * (b ^ 2 - 1) = (b ^ (2 * p) - 1) / (b ^ 2 - 1) * (b ^ 2 - 1)
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
rw [Nat.div_mul_cancel hd] at AB_id
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : A * B * (b ^ 2 - 1) = b ^ (2 * p) - 1
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
apply_fun fun x => x - (b ^ 2 - 1) at AB_id
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : A * B * (b ^ 2 - 1) - (b ^ 2 - 1) = b ^ (2 * p) - 1 - (b ^ 2 - 1)
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
nth_rw 2 [← one_mul (b ^ 2 - 1)] at AB_id
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : A * B * (b ^ 2 - 1) - 1 * (b ^ 2 - 1) = b ^ (2 * p) - 1 - (b ^ 2 - 1)
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
rw [← Nat.mul_sub_right_distrib, mul_comm] at AB_id
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : (b ^ 2 - 1) * (A * B - 1) = b ^ (2 * p) - 1 - (b ^ 2 - 1)
⊢ (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
rw [AB_id]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
AB_id : (b ^ 2 - 1) * (A * B - 1) = b ^ (2 * p) - 1 - (b ^ 2 - 1)
⊢ b ^ (2 * p) - 1 - (b ^ 2 - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
exact bp_helper hi_b hi_p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₂ : 2 ∣ b ^ p + b := by
  -- Porting note: golfedrw [← even_iff_two_dvd, Nat.even_add, Nat.even_pow' p_prime.ne_zero]
    -- Since `b` isn't divisible by `p`, `b` is coprime with `p`. we can use Fermat's Little Theorem
      -- to prove this.
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
⊢ 2 ∣ b ^ p + b
[PROOFSTEP]
rw [← even_iff_two_dvd, Nat.even_add, Nat.even_pow' p_prime.ne_zero]
  -- Since `b` isn't divisible by `p`, `b` is coprime with `p`. we can use Fermat's Little Theorem
    -- to prove this.
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₃ : p ∣ b ^ (p - 1) - 1 :=
  by
  have : ¬p ∣ b := mt (fun h : p ∣ b => dvd_mul_of_dvd_left h _) not_dvd
  have : p.coprime b := Or.resolve_right (Nat.coprime_or_dvd_of_prime p_prime b) this
  have : IsCoprime (b : ℤ) ↑p := this.symm.isCoprime
  have : ↑b ^ (p - 1) ≡ 1 [ZMOD ↑p] := Int.ModEq.pow_card_sub_one_eq_one p_prime this
  have : ↑p ∣ ↑b ^ (p - 1) - ↑1 := by exact_mod_cast Int.ModEq.dvd (Int.ModEq.symm this)
  exact_mod_cast this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : ¬p ∣ b := mt (fun h : p ∣ b => dvd_mul_of_dvd_left h _) not_dvd
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this : ¬p ∣ b
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : p.coprime b := Or.resolve_right (Nat.coprime_or_dvd_of_prime p_prime b) this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this✝ : ¬p ∣ b
this : coprime p b
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : IsCoprime (b : ℤ) ↑p := this.symm.isCoprime
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this✝¹ : ¬p ∣ b
this✝ : coprime p b
this : IsCoprime ↑b ↑p
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : ↑b ^ (p - 1) ≡ 1 [ZMOD ↑p] := Int.ModEq.pow_card_sub_one_eq_one p_prime this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this✝² : ¬p ∣ b
this✝¹ : coprime p b
this✝ : IsCoprime ↑b ↑p
this : ↑b ^ (p - 1) ≡ 1 [ZMOD ↑p]
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : ↑p ∣ ↑b ^ (p - 1) - ↑1 := by exact_mod_cast Int.ModEq.dvd (Int.ModEq.symm this)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this✝² : ¬p ∣ b
this✝¹ : coprime p b
this✝ : IsCoprime ↑b ↑p
this : ↑b ^ (p - 1) ≡ 1 [ZMOD ↑p]
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
exact_mod_cast Int.ModEq.dvd (Int.ModEq.symm this)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
this✝³ : ¬p ∣ b
this✝² : coprime p b
this✝¹ : IsCoprime ↑b ↑p
this✝ : ↑b ^ (p - 1) ≡ 1 [ZMOD ↑p]
this : p ∣ b ^ (p - 1) - 1
⊢ p ∣ b ^ (p - 1) - 1
[PROOFSTEP]
exact_mod_cast this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1 := by
  cases' p_odd with k hk
  have : 2 ∣ p - 1 := ⟨k, by simp [hk]⟩
  cases' this with c hc
  have : b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1 := by simpa only [one_pow] using nat_sub_dvd_pow_sub_pow _ 1 c
  have : b ^ 2 - 1 ∣ b ^ (2 * c) - 1 := by rwa [← pow_mul] at this
  rwa [← hc] at this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
cases' p_odd with k hk
[GOAL]
case intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : 2 ∣ p - 1 := ⟨k, by simp [hk]⟩
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
⊢ p - 1 = 2 * k
[PROOFSTEP]
simp [hk]
[GOAL]
case intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
this : 2 ∣ p - 1
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
cases' this with c hc
[GOAL]
case intro.intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
c : ℕ
hc : p - 1 = 2 * c
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1 := by simpa only [one_pow] using nat_sub_dvd_pow_sub_pow _ 1 c
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
c : ℕ
hc : p - 1 = 2 * c
⊢ b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1
[PROOFSTEP]
simpa only [one_pow] using nat_sub_dvd_pow_sub_pow _ 1 c
[GOAL]
case intro.intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
c : ℕ
hc : p - 1 = 2 * c
this : b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
have : b ^ 2 - 1 ∣ b ^ (2 * c) - 1 := by rwa [← pow_mul] at this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
c : ℕ
hc : p - 1 = 2 * c
this : b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1
⊢ b ^ 2 - 1 ∣ b ^ (2 * c) - 1
[PROOFSTEP]
rwa [← pow_mul] at this
[GOAL]
case intro.intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
k : ℕ
hk : p = 2 * k + 1
c : ℕ
hc : p - 1 = 2 * c
this✝ : b ^ 2 - 1 ∣ (b ^ 2) ^ c - 1
this : b ^ 2 - 1 ∣ b ^ (2 * c) - 1
⊢ b ^ 2 - 1 ∣ b ^ (p - 1) - 1
[PROOFSTEP]
rwa [← hc] at this
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1) :=
  by
  suffices q : 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
  ·
    rwa [ha₁]
      -- We already proved that `b ^ 2 - 1 ∣ b ^ (p - 1) - 1`.
          -- Since `2 ∣ b ^ p + b` and `p ∣ b ^ p + b`, if we show that 2 and p are coprime, then we
          -- know that `2 * p ∣ b ^ p + b`
  have q₁ : Nat.coprime p (b ^ 2 - 1) :=
    haveI q₂ : ¬p ∣ b ^ 2 - 1 := by
      rw [mul_comm] at not_dvd
      exact mt (fun h : p ∣ b ^ 2 - 1 => dvd_mul_of_dvd_left h _) not_dvd
    (Nat.Prime.coprime_iff_not_dvd p_prime).mpr q₂
  have q₂ : p * (b ^ 2 - 1) ∣ b ^ (p - 1) - 1 := Nat.coprime.mul_dvd_of_dvd_of_dvd q₁ ha₃ ha₄
  have q₃ : p * (b ^ 2 - 1) * 2 ∣ (b ^ (p - 1) - 1) * (b ^ p + b) := mul_dvd_mul q₂ ha₂
  have q₄ : p * (b ^ 2 - 1) * 2 ∣ b * ((b ^ (p - 1) - 1) * (b ^ p + b)) := dvd_mul_of_dvd_right q₃ _
  rwa [mul_assoc, mul_comm, mul_assoc b]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
⊢ 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
[PROOFSTEP]
suffices q : 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
q : 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
⊢ 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
[PROOFSTEP]
rwa [ha₁]
  -- We already proved that `b ^ 2 - 1 ∣ b ^ (p - 1) - 1`.
      -- Since `2 ∣ b ^ p + b` and `p ∣ b ^ p + b`, if we show that 2 and p are coprime, then we
      -- know that `2 * p ∣ b ^ p + b`
[GOAL]
case q
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
⊢ 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
have q₁ : Nat.coprime p (b ^ 2 - 1) :=
  haveI q₂ : ¬p ∣ b ^ 2 - 1 := by
    rw [mul_comm] at not_dvd
    exact mt (fun h : p ∣ b ^ 2 - 1 => dvd_mul_of_dvd_left h _) not_dvd
  (Nat.Prime.coprime_iff_not_dvd p_prime).mpr q₂
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
⊢ ¬p ∣ b ^ 2 - 1
[PROOFSTEP]
rw [mul_comm] at not_dvd
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ (b ^ 2 - 1) * b
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
⊢ ¬p ∣ b ^ 2 - 1
[PROOFSTEP]
exact mt (fun h : p ∣ b ^ 2 - 1 => dvd_mul_of_dvd_left h _) not_dvd
[GOAL]
case q
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
q₁ : coprime p (b ^ 2 - 1)
⊢ 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
have q₂ : p * (b ^ 2 - 1) ∣ b ^ (p - 1) - 1 := Nat.coprime.mul_dvd_of_dvd_of_dvd q₁ ha₃ ha₄
[GOAL]
case q
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
q₁ : coprime p (b ^ 2 - 1)
q₂ : p * (b ^ 2 - 1) ∣ b ^ (p - 1) - 1
⊢ 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
have q₃ : p * (b ^ 2 - 1) * 2 ∣ (b ^ (p - 1) - 1) * (b ^ p + b) := mul_dvd_mul q₂ ha₂
[GOAL]
case q
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
q₁ : coprime p (b ^ 2 - 1)
q₂ : p * (b ^ 2 - 1) ∣ b ^ (p - 1) - 1
q₃ : p * (b ^ 2 - 1) * 2 ∣ (b ^ (p - 1) - 1) * (b ^ p + b)
⊢ 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
have q₄ : p * (b ^ 2 - 1) * 2 ∣ b * ((b ^ (p - 1) - 1) * (b ^ p + b)) := dvd_mul_of_dvd_right q₃ _
[GOAL]
case q
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
q₁ : coprime p (b ^ 2 - 1)
q₂ : p * (b ^ 2 - 1) ∣ b ^ (p - 1) - 1
q₃ : p * (b ^ 2 - 1) * 2 ∣ (b ^ (p - 1) - 1) * (b ^ p + b)
q₄ : p * (b ^ 2 - 1) * 2 ∣ b * ((b ^ (p - 1) - 1) * (b ^ p + b))
⊢ 2 * p * (b ^ 2 - 1) ∣ b * (b ^ (p - 1) - 1) * (b ^ p + b)
[PROOFSTEP]
rwa [mul_assoc, mul_comm, mul_assoc b]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₆ : 2 * p ∣ A * B - 1 := by
  rw [mul_comm] at ha₅
  exact Nat.dvd_of_mul_dvd_mul_left hi_bsquared ha₅
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
⊢ 2 * p ∣ A * B - 1
[PROOFSTEP]
rw [mul_comm] at ha₅
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : (b ^ 2 - 1) * (2 * p) ∣ (b ^ 2 - 1) * (A * B - 1)
⊢ 2 * p ∣ A * B - 1
[PROOFSTEP]
exact Nat.dvd_of_mul_dvd_mul_left hi_bsquared ha₅
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₆ : 2 * p ∣ A * B - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₇ : A * B ∣ b ^ (2 * p) - 1 := by
  use b ^ 2 - 1
  have : A * B * (b ^ 2 - 1) = (b ^ (2 * p) - 1) / (b ^ 2 - 1) * (b ^ 2 - 1) :=
    congr_arg (fun x : ℕ => x * (b ^ 2 - 1)) AB_id
  simpa only [add_comm, Nat.div_mul_cancel hd, Nat.sub_add_cancel hi_bpowtwop] using this.symm
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₆ : 2 * p ∣ A * B - 1
⊢ A * B ∣ b ^ (2 * p) - 1
[PROOFSTEP]
use b ^ 2 - 1
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₆ : 2 * p ∣ A * B - 1
⊢ b ^ (2 * p) - 1 = A * B * (b ^ 2 - 1)
[PROOFSTEP]
have : A * B * (b ^ 2 - 1) = (b ^ (2 * p) - 1) / (b ^ 2 - 1) * (b ^ 2 - 1) :=
  congr_arg (fun x : ℕ => x * (b ^ 2 - 1)) AB_id
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₆ : 2 * p ∣ A * B - 1
this : A * B * (b ^ 2 - 1) = (b ^ (2 * p) - 1) / (b ^ 2 - 1) * (b ^ 2 - 1)
⊢ b ^ (2 * p) - 1 = A * B * (b ^ 2 - 1)
[PROOFSTEP]
simpa only [add_comm, Nat.div_mul_cancel hd, Nat.sub_add_cancel hi_bpowtwop] using this.symm
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₆ : 2 * p ∣ A * B - 1
ha₇ : A * B ∣ b ^ (2 * p) - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
cases' ha₆ with q hq
[GOAL]
case intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₇ : A * B ∣ b ^ (2 * p) - 1
q : ℕ
hq : A * B - 1 = 2 * p * q
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
have ha₈ : b ^ (2 * p) - 1 ∣ b ^ (A * B - 1) - 1 := by
  simpa only [one_pow, pow_mul, hq] using nat_sub_dvd_pow_sub_pow _ 1 q
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₇ : A * B ∣ b ^ (2 * p) - 1
q : ℕ
hq : A * B - 1 = 2 * p * q
⊢ b ^ (2 * p) - 1 ∣ b ^ (A * B - 1) - 1
[PROOFSTEP]
simpa only [one_pow, pow_mul, hq] using nat_sub_dvd_pow_sub_pow _ 1 q
[GOAL]
case intro
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
not_dvd : ¬p ∣ b * (b ^ 2 - 1)
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
hi_A : 1 < A
hi_B : 1 < B
hi_AB : 1 < A * B
hi_b : 0 < b
hi_p : 1 ≤ p
hi_bsquared : 0 < b ^ 2 - 1
hi_bpowtwop : 1 ≤ b ^ (2 * p)
hi_bpowpsubone : 1 ≤ b ^ (p - 1)
p_odd : Odd p
AB_not_prime : ¬Prime (A * B)
AB_id : A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1)
hd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
ha₁ : (b ^ 2 - 1) * (A * B - 1) = b * (b ^ (p - 1) - 1) * (b ^ p + b)
ha₂ : 2 ∣ b ^ p + b
ha₃ : p ∣ b ^ (p - 1) - 1
ha₄ : b ^ 2 - 1 ∣ b ^ (p - 1) - 1
ha₅ : 2 * p * (b ^ 2 - 1) ∣ (b ^ 2 - 1) * (A * B - 1)
ha₇ : A * B ∣ b ^ (2 * p) - 1
q : ℕ
hq : A * B - 1 = 2 * p * q
ha₈ : b ^ (2 * p) - 1 ∣ b ^ (A * B - 1) - 1
⊢ ProbablePrime (A * B) b
[PROOFSTEP]
exact dvd_trans ha₇ ha₈
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
⊢ p < Nat.psp_from_prime b p
[PROOFSTEP]
unfold psp_from_prime
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
⊢ p < (b ^ p - 1) / (b - 1) * ((b ^ p + 1) / (b + 1))
[PROOFSTEP]
set A := (b ^ p - 1) / (b - 1)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
⊢ p < A * ((b ^ p + 1) / (b + 1))
[PROOFSTEP]
set B := (b ^ p + 1) / (b + 1)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
⊢ p < A * B
[PROOFSTEP]
rw [show A * B = (b ^ (2 * p) - 1) / (b ^ 2 - 1) from
    AB_id_helper _ _ b_ge_two (p_prime.odd_of_ne_two p_gt_two.ne.symm)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
⊢ p < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
have AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1 := by simpa only [one_pow, pow_mul] using nat_sub_dvd_pow_sub_pow _ 1 p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
⊢ b ^ 2 - 1 ∣ b ^ (2 * p) - 1
[PROOFSTEP]
simpa only [one_pow, pow_mul] using nat_sub_dvd_pow_sub_pow _ 1 p
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
suffices h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
⊢ p < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
have h₁ : p * (b ^ 2 - 1) / (b ^ 2 - 1) < (b ^ (2 * p) - 1) / (b ^ 2 - 1) := Nat.div_lt_div_of_lt_of_dvd AB_dvd h
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
h₁ : p * (b ^ 2 - 1) / (b ^ 2 - 1) < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
⊢ p < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
have h₂ : 0 < b ^ 2 - 1 := by linarith [show 3 ≤ b ^ 2 - 1 from le_tsub_of_add_le_left (show 4 ≤ b ^ 2 by nlinarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
h₁ : p * (b ^ 2 - 1) / (b ^ 2 - 1) < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
⊢ 0 < b ^ 2 - 1
[PROOFSTEP]
linarith [show 3 ≤ b ^ 2 - 1 from le_tsub_of_add_le_left (show 4 ≤ b ^ 2 by nlinarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
h₁ : p * (b ^ 2 - 1) / (b ^ 2 - 1) < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
⊢ 4 ≤ b ^ 2
[PROOFSTEP]
nlinarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * (b ^ 2 - 1) < b ^ (2 * p) - 1
h₁ : p * (b ^ 2 - 1) / (b ^ 2 - 1) < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
h₂ : 0 < b ^ 2 - 1
⊢ p < (b ^ (2 * p) - 1) / (b ^ 2 - 1)
[PROOFSTEP]
rwa [Nat.mul_div_cancel _ h₂] at h₁
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p * (b ^ 2 - 1) < b ^ (2 * p) - 1
[PROOFSTEP]
rw [Nat.mul_sub_left_distrib, mul_one, pow_mul]
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p * b ^ 2 - p < (b ^ 2) ^ p - 1
[PROOFSTEP]
conv_rhs => rw [← Nat.sub_add_cancel (show 1 ≤ p by linarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
| (b ^ 2) ^ p - 1
[PROOFSTEP]
rw [← Nat.sub_add_cancel (show 1 ≤ p by linarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
| (b ^ 2) ^ p - 1
[PROOFSTEP]
rw [← Nat.sub_add_cancel (show 1 ≤ p by linarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
| (b ^ 2) ^ p - 1
[PROOFSTEP]
rw [← Nat.sub_add_cancel (show 1 ≤ p by linarith)]
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ 1 ≤ p
[PROOFSTEP]
linarith
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p * b ^ 2 - p < (b ^ 2) ^ (p - 1 + 1) - 1
[PROOFSTEP]
rw [pow_succ (b ^ 2)]
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p * b ^ 2 - p < (b ^ 2) ^ (p - 1) * b ^ 2 - 1
[PROOFSTEP]
suffices h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
⊢ p * b ^ 2 - p < (b ^ 2) ^ (p - 1) * b ^ 2 - 1
[PROOFSTEP]
apply gt_of_ge_of_gt
[GOAL]
case h.h₁
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
⊢ (b ^ 2) ^ (p - 1) * b ^ 2 - 1 ≥ ?h.b
[PROOFSTEP]
exact tsub_le_tsub_left (one_le_of_lt p_gt_two) ((b ^ 2) ^ (p - 1) * b ^ 2)
[GOAL]
case h.h₂
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
⊢ (b ^ 2) ^ (p - 1) * b ^ 2 - p > p * b ^ 2 - p
[PROOFSTEP]
have : p ≤ p * b ^ 2 := Nat.le_mul_of_pos_right (show 0 < b ^ 2 by nlinarith)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
⊢ 0 < b ^ 2
[PROOFSTEP]
nlinarith
[GOAL]
case h.h₂
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
this : p ≤ p * b ^ 2
⊢ (b ^ 2) ^ (p - 1) * b ^ 2 - p > p * b ^ 2 - p
[PROOFSTEP]
exact tsub_lt_tsub_right_of_le this h
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
[PROOFSTEP]
suffices h : p < (b ^ 2) ^ (p - 1)
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p < (b ^ 2) ^ (p - 1)
⊢ p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
[PROOFSTEP]
have : 4 ≤ b ^ 2 := by nlinarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p < (b ^ 2) ^ (p - 1)
⊢ 4 ≤ b ^ 2
[PROOFSTEP]
nlinarith
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p < (b ^ 2) ^ (p - 1)
this : 4 ≤ b ^ 2
⊢ p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
[PROOFSTEP]
have : 0 < b ^ 2 := by linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p < (b ^ 2) ^ (p - 1)
this : 4 ≤ b ^ 2
⊢ 0 < b ^ 2
[PROOFSTEP]
linarith
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
h : p < (b ^ 2) ^ (p - 1)
this✝ : 4 ≤ b ^ 2
this : 0 < b ^ 2
⊢ p * b ^ 2 < (b ^ 2) ^ (p - 1) * b ^ 2
[PROOFSTEP]
exact mul_lt_mul_of_pos_right h this
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p < (b ^ 2) ^ (p - 1)
[PROOFSTEP]
rw [← pow_mul, Nat.mul_sub_left_distrib, mul_one]
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ p < b ^ (2 * p - 2)
[PROOFSTEP]
have : 2 ≤ 2 * p - 2 := le_tsub_of_add_le_left (show 4 ≤ 2 * p by linarith)
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
⊢ 4 ≤ 2 * p
[PROOFSTEP]
linarith
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
this : 2 ≤ 2 * p - 2
⊢ p < b ^ (2 * p - 2)
[PROOFSTEP]
have : 2 + p ≤ 2 * p := by linarith
[GOAL]
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
this : 2 ≤ 2 * p - 2
⊢ 2 + p ≤ 2 * p
[PROOFSTEP]
linarith
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
this✝ : 2 ≤ 2 * p - 2
this : 2 + p ≤ 2 * p
⊢ p < b ^ (2 * p - 2)
[PROOFSTEP]
have : p ≤ 2 * p - 2 := le_tsub_of_add_le_left this
[GOAL]
case h
b : ℕ
b_ge_two : 2 ≤ b
p : ℕ
p_prime : Prime p
p_gt_two : 2 < p
A : ℕ := (b ^ p - 1) / (b - 1)
B : ℕ := (b ^ p + 1) / (b + 1)
AB_dvd : b ^ 2 - 1 ∣ b ^ (2 * p) - 1
this✝¹ : 2 ≤ 2 * p - 2
this✝ : 2 + p ≤ 2 * p
this : p ≤ 2 * p - 2
⊢ p < b ^ (2 * p - 2)
[PROOFSTEP]
exact Nat.lt_of_le_of_lt this (pow_gt_exponent _ b_ge_two)
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
by_cases b_ge_two : 2 ≤ b
[GOAL]
case pos
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h := Nat.exists_infinite_primes (b * (b ^ 2 - 1) + 1 + m)
[GOAL]
case pos
b : ℕ
h✝ : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
h : ∃ p, b * (b ^ 2 - 1) + 1 + m ≤ p ∧ Prime p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
cases' h with p hp
[GOAL]
case pos.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp : b * (b ^ 2 - 1) + 1 + m ≤ p ∧ Prime p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
cases' hp with hp₁ hp₂
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₁ : 0 < b := pos_of_gt (Nat.succ_le_iff.mp b_ge_two)
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₂ : 4 ≤ b ^ 2 := pow_le_pow_of_le_left' b_ge_two 2
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₃ : 0 < b ^ 2 - 1 := tsub_pos_of_lt (gt_of_ge_of_gt h₂ (by norm_num))
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
⊢ 4 > 1
[PROOFSTEP]
norm_num
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₄ : 0 < b * (b ^ 2 - 1) := mul_pos h₁ h₃
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₅ : b * (b ^ 2 - 1) < p := by linarith
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
⊢ b * (b ^ 2 - 1) < p
[PROOFSTEP]
linarith
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₆ : ¬p ∣ b * (b ^ 2 - 1) := Nat.not_dvd_of_pos_of_lt h₄ h₅
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₇ : b ≤ b * (b ^ 2 - 1) := Nat.le_mul_of_pos_right h₃
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₈ : 2 ≤ b * (b ^ 2 - 1) := le_trans b_ge_two h₇
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₉ : 2 < p := gt_of_gt_of_ge h₅ h₈
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₁₀ := psp_from_prime_gt_p b_ge_two hp₂ h₉
[GOAL]
case pos.intro.intro
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
h₁₀ : p < Nat.psp_from_prime b p
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
use psp_from_prime b p
[GOAL]
case h
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
h₁₀ : p < Nat.psp_from_prime b p
⊢ FermatPsp (Nat.psp_from_prime b p) b ∧ m ≤ Nat.psp_from_prime b p
[PROOFSTEP]
constructor
[GOAL]
case h.left
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
h₁₀ : p < Nat.psp_from_prime b p
⊢ FermatPsp (Nat.psp_from_prime b p) b
[PROOFSTEP]
exact psp_from_prime_psp b_ge_two hp₂ h₉ h₆
[GOAL]
case h.right
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
h₁₀ : p < Nat.psp_from_prime b p
⊢ m ≤ Nat.psp_from_prime b p
[PROOFSTEP]
exact
  le_trans (show m ≤ p by linarith)
    (le_of_lt h₁₀)
      -- If `¬2 ≤ b`, then `b = 1`. Since all composite numbers are pseudoprimes to base 1, we can pick
        -- any composite number greater than m. We choose `2 * (m + 2)` because it is greater than `m` and
        -- is composite for all natural numbers `m`.
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : 2 ≤ b
p : ℕ
hp₁ : b * (b ^ 2 - 1) + 1 + m ≤ p
hp₂ : Prime p
h₁ : 0 < b
h₂ : 4 ≤ b ^ 2
h₃ : 0 < b ^ 2 - 1
h₄ : 0 < b * (b ^ 2 - 1)
h₅ : b * (b ^ 2 - 1) < p
h₆ : ¬p ∣ b * (b ^ 2 - 1)
h₇ : b ≤ b * (b ^ 2 - 1)
h₈ : 2 ≤ b * (b ^ 2 - 1)
h₉ : 2 < p
h₁₀ : p < Nat.psp_from_prime b p
⊢ m ≤ p
[PROOFSTEP]
linarith
[GOAL]
case neg
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
have h₁ : b = 1 := by linarith
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
⊢ b = 1
[PROOFSTEP]
linarith
[GOAL]
case neg
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
⊢ ∃ n, FermatPsp n b ∧ m ≤ n
[PROOFSTEP]
rw [h₁]
[GOAL]
case neg
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
⊢ ∃ n, FermatPsp n 1 ∧ m ≤ n
[PROOFSTEP]
use 2 * (m + 2)
[GOAL]
case h
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
⊢ FermatPsp (2 * (m + 2)) 1 ∧ m ≤ 2 * (m + 2)
[PROOFSTEP]
have : ¬Nat.Prime (2 * (m + 2)) := Nat.not_prime_mul (by norm_num) (by norm_num)
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
⊢ 1 < 2
[PROOFSTEP]
norm_num
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
⊢ 1 < m + 2
[PROOFSTEP]
norm_num
[GOAL]
case h
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ FermatPsp (2 * (m + 2)) 1 ∧ m ≤ 2 * (m + 2)
[PROOFSTEP]
exact ⟨fermatPsp_base_one (by linarith) this, by linarith⟩
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ 1 < 2 * (m + 2)
[PROOFSTEP]
linarith
[GOAL]
b : ℕ
h : 1 ≤ b
m : ℕ
b_ge_two : ¬2 ≤ b
h₁ : b = 1
this : ¬Prime (2 * (m + 2))
⊢ m ≤ 2 * (m + 2)
[PROOFSTEP]
linarith
[GOAL]
b : ℕ
h : 1 ≤ b
⊢ ∃ᶠ (n : ℕ) in Filter.atTop, FermatPsp n b
[PROOFSTEP]
refine' Filter.frequently_atTop.2 fun n => _
[GOAL]
b : ℕ
h : 1 ≤ b
n : ℕ
⊢ ∃ b_1, b_1 ≥ n ∧ FermatPsp b_1 b
[PROOFSTEP]
obtain ⟨p, hp⟩ := exists_infinite_pseudoprimes h n
[GOAL]
case intro
b : ℕ
h : 1 ≤ b
n p : ℕ
hp : FermatPsp p b ∧ n ≤ p
⊢ ∃ b_1, b_1 ≥ n ∧ FermatPsp b_1 b
[PROOFSTEP]
exact ⟨p, hp.2, hp.1⟩


[GOAL]
α : Type u_1
β : Type u_2
l : List α
⊢ join [l] = l
[PROOFSTEP]
rw [join, join, append_nil]
[GOAL]
α : Type u_1
β : Type u_2
l : List α
L : List (List α)
⊢ join (l :: L) = [] ↔ ∀ (l_1 : List α), l_1 ∈ l :: L → l_1 = []
[PROOFSTEP]
simp only [join, append_eq_nil, join_eq_nil, forall_mem_cons]
[GOAL]
α : Type u_1
β : Type u_2
L₁ L₂ : List (List α)
⊢ join (L₁ ++ L₂) = join L₁ ++ join L₂
[PROOFSTEP]
induction L₁
[GOAL]
case nil
α : Type u_1
β : Type u_2
L₂ : List (List α)
⊢ join ([] ++ L₂) = join [] ++ join L₂
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type u_1
β : Type u_2
L₂ : List (List α)
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : join (tail✝ ++ L₂) = join tail✝ ++ join L₂
⊢ join (head✝ :: tail✝ ++ L₂) = join (head✝ :: tail✝) ++ join L₂
[PROOFSTEP]
simp [*]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
l : List α
⊢ join (concat L l) = join L ++ l
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : DecidablePred fun l => isEmpty l = false
L : List (List α)
⊢ join (filter (fun l => decide (isEmpty l = false)) ([] :: L)) = join ([] :: L)
[PROOFSTEP]
simp [join_filter_isEmpty_eq_false (L := L), isEmpty_iff_eq_nil]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : DecidablePred fun l => isEmpty l = false
a : α
l : List α
L : List (List α)
⊢ join (filter (fun l => decide (isEmpty l = false)) ((a :: l) :: L)) = join ((a :: l) :: L)
[PROOFSTEP]
have cons_not_empty : isEmpty (a :: l) = false := rfl
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : DecidablePred fun l => isEmpty l = false
a : α
l : List α
L : List (List α)
cons_not_empty : isEmpty (a :: l) = false
⊢ join (filter (fun l => decide (isEmpty l = false)) ((a :: l) :: L)) = join ((a :: l) :: L)
[PROOFSTEP]
simp [join_filter_isEmpty_eq_false (L := L), cons_not_empty]
[GOAL]
α : Type u_1
β : Type u_2
inst✝ : DecidablePred fun l => l ≠ []
L : List (List α)
⊢ join (filter (fun l => decide (l ≠ [])) L) = join L
[PROOFSTEP]
simp [join_filter_isEmpty_eq_false, ← isEmpty_iff_eq_nil]
[GOAL]
α : Type u_1
β : Type u_2
l : List (List (List α))
⊢ join (join l) = join (map join l)
[PROOFSTEP]
induction l
[GOAL]
case nil
α : Type u_1
β : Type u_2
⊢ join (join []) = join (map join [])
[PROOFSTEP]
simp [*]
[GOAL]
case cons
α : Type u_1
β : Type u_2
head✝ : List (List α)
tail✝ : List (List (List α))
tail_ih✝ : join (join tail✝) = join (map join tail✝)
⊢ join (join (head✝ :: tail✝)) = join (map join (head✝ :: tail✝))
[PROOFSTEP]
simp [*]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
⊢ length (join L) = sum (map length L)
[PROOFSTEP]
induction L <;> [rfl; simp only [*, join, map, sum_cons, length_append]]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
⊢ length (join L) = sum (map length L)
[PROOFSTEP]
induction L
[GOAL]
case nil
α : Type u_1
β : Type u_2
⊢ length (join []) = sum (map length [])
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : length (join tail✝) = sum (map length tail✝)
⊢ length (join (head✝ :: tail✝)) = sum (map length (head✝ :: tail✝))
[PROOFSTEP]
simp only [*, join, map, sum_cons, length_append]
[GOAL]
α : Type u_1
β : Type u_2
l : List α
f : α → List β
⊢ length (List.bind l f) = sum (map (length ∘ f) l)
[PROOFSTEP]
rw [List.bind, length_join, map_map]
[GOAL]
α : Type u_1
β : Type u_2
l : List α
f : α → List β
⊢ (∀ (l_1 : List β), l_1 ∈ map f l → l_1 = []) ↔ ∀ (x : α), x ∈ l → f x = []
[PROOFSTEP]
simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : ℕ
⊢ take (sum (take i (map length L))) (join L) = join (take i L)
[PROOFSTEP]
induction L generalizing i
[GOAL]
case nil
α : Type u_1
β : Type u_2
i : ℕ
⊢ take (sum (take i (map length []))) (join []) = join (take i [])
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), take (sum (take i (map length tail✝))) (join tail✝) = join (take i tail✝)
i : ℕ
⊢ take (sum (take i (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) = join (take i (head✝ :: tail✝))
[PROOFSTEP]
cases i
[GOAL]
case cons.zero
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), take (sum (take i (map length tail✝))) (join tail✝) = join (take i tail✝)
⊢ take (sum (take Nat.zero (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) =
    join (take Nat.zero (head✝ :: tail✝))
[PROOFSTEP]
simp [take_append, *]
[GOAL]
case cons.succ
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), take (sum (take i (map length tail✝))) (join tail✝) = join (take i tail✝)
n✝ : ℕ
⊢ take (sum (take (Nat.succ n✝) (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) =
    join (take (Nat.succ n✝) (head✝ :: tail✝))
[PROOFSTEP]
simp [take_append, *]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : ℕ
⊢ drop (sum (take i (map length L))) (join L) = join (drop i L)
[PROOFSTEP]
induction L generalizing i
[GOAL]
case nil
α : Type u_1
β : Type u_2
i : ℕ
⊢ drop (sum (take i (map length []))) (join []) = join (drop i [])
[PROOFSTEP]
simp
[GOAL]
case cons
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), drop (sum (take i (map length tail✝))) (join tail✝) = join (drop i tail✝)
i : ℕ
⊢ drop (sum (take i (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) = join (drop i (head✝ :: tail✝))
[PROOFSTEP]
cases i
[GOAL]
case cons.zero
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), drop (sum (take i (map length tail✝))) (join tail✝) = join (drop i tail✝)
⊢ drop (sum (take Nat.zero (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) =
    join (drop Nat.zero (head✝ :: tail✝))
[PROOFSTEP]
simp [drop_append, *]
[GOAL]
case cons.succ
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
tail_ih✝ : ∀ (i : ℕ), drop (sum (take i (map length tail✝))) (join tail✝) = join (drop i tail✝)
n✝ : ℕ
⊢ drop (sum (take (Nat.succ n✝) (map length (head✝ :: tail✝)))) (join (head✝ :: tail✝)) =
    join (drop (Nat.succ n✝) (head✝ :: tail✝))
[PROOFSTEP]
simp [drop_append, *]
[GOAL]
α : Type u_1
β : Type u_2
L : List α
i : Fin (length L)
⊢ drop (↑i) (take (↑i + 1) L) = [get L i]
[PROOFSTEP]
induction' L with head tail ih
[GOAL]
case nil
α : Type u_1
β : Type u_2
L : List α
i✝ : Fin (length L)
i : Fin (length [])
⊢ drop (↑i) (take (↑i + 1) []) = [get [] i]
[PROOFSTEP]
exact (Nat.not_succ_le_zero i i.isLt).elim
[GOAL]
case cons
α : Type u_1
β : Type u_2
L : List α
i✝ : Fin (length L)
head : α
tail : List α
ih : ∀ (i : Fin (length tail)), drop (↑i) (take (↑i + 1) tail) = [get tail i]
i : Fin (length (head :: tail))
⊢ drop (↑i) (take (↑i + 1) (head :: tail)) = [get (head :: tail) i]
[PROOFSTEP]
rcases i with ⟨_ | i, hi⟩
[GOAL]
case cons.mk.zero
α : Type u_1
β : Type u_2
L : List α
i : Fin (length L)
head : α
tail : List α
ih : ∀ (i : Fin (length tail)), drop (↑i) (take (↑i + 1) tail) = [get tail i]
hi : Nat.zero < length (head :: tail)
⊢ drop (↑{ val := Nat.zero, isLt := hi }) (take (↑{ val := Nat.zero, isLt := hi } + 1) (head :: tail)) =
    [get (head :: tail) { val := Nat.zero, isLt := hi }]
[PROOFSTEP]
simp
[GOAL]
case cons.mk.succ
α : Type u_1
β : Type u_2
L : List α
i✝ : Fin (length L)
head : α
tail : List α
ih : ∀ (i : Fin (length tail)), drop (↑i) (take (↑i + 1) tail) = [get tail i]
i : ℕ
hi : Nat.succ i < length (head :: tail)
⊢ drop (↑{ val := Nat.succ i, isLt := hi }) (take (↑{ val := Nat.succ i, isLt := hi } + 1) (head :: tail)) =
    [get (head :: tail) { val := Nat.succ i, isLt := hi }]
[PROOFSTEP]
simpa using ih ⟨i, Nat.lt_of_succ_lt_succ hi⟩
[GOAL]
α : Type u_1
β : Type u_2
L : List α
i : ℕ
hi : i < length L
⊢ drop i (take (i + 1) L) = [nthLe L i hi]
[PROOFSTEP]
induction' L with head tail generalizing i
[GOAL]
case nil
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
i : ℕ
hi : i < length []
⊢ drop i (take (i + 1) []) = [nthLe [] i hi]
[PROOFSTEP]
simp only [length] at hi
[GOAL]
case nil
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
i : ℕ
hi : i < 0
⊢ drop i (take (i + 1) []) = [nthLe [] i hi]
[PROOFSTEP]
exact (Nat.not_succ_le_zero i hi).elim
[GOAL]
case cons
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : i < length (head :: tail)
⊢ drop i (take (i + 1) (head :: tail)) = [nthLe (head :: tail) i hi]
[PROOFSTEP]
cases' i with i hi
[GOAL]
case cons.zero
α : Type u_1
β : Type u_2
L : List α
i : ℕ
hi✝ : i < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
hi : Nat.zero < length (head :: tail)
⊢ drop Nat.zero (take (Nat.zero + 1) (head :: tail)) = [nthLe (head :: tail) Nat.zero hi]
[PROOFSTEP]
simp
[GOAL]
case cons.zero
α : Type u_1
β : Type u_2
L : List α
i : ℕ
hi✝ : i < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
hi : Nat.zero < length (head :: tail)
⊢ head = nthLe (head :: tail) 0 hi
[PROOFSTEP]
rfl
[GOAL]
case cons.succ
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : Nat.succ i < length (head :: tail)
⊢ drop (Nat.succ i) (take (Nat.succ i + 1) (head :: tail)) = [nthLe (head :: tail) (Nat.succ i) hi]
[PROOFSTEP]
have : i < tail.length := by
  simp at hi
  exact Nat.lt_of_succ_lt_succ hi
[GOAL]
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : Nat.succ i < length (head :: tail)
⊢ i < length tail
[PROOFSTEP]
simp at hi
[GOAL]
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : Nat.succ i < Nat.succ (length tail)
⊢ i < length tail
[PROOFSTEP]
exact Nat.lt_of_succ_lt_succ hi
[GOAL]
case cons.succ
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : Nat.succ i < length (head :: tail)
this : i < length tail
⊢ drop (Nat.succ i) (take (Nat.succ i + 1) (head :: tail)) = [nthLe (head :: tail) (Nat.succ i) hi]
[PROOFSTEP]
simp [*]
[GOAL]
case cons.succ
α : Type u_1
β : Type u_2
L : List α
i✝ : ℕ
hi✝ : i✝ < length L
head : α
tail : List α
tail_ih✝ : ∀ {i : ℕ} (hi : i < length tail), drop i (take (i + 1) tail) = [nthLe tail i hi]
i : ℕ
hi : Nat.succ i < length (head :: tail)
this : i < length tail
⊢ nthLe tail i (_ : i < length tail) = nthLe (head :: tail) (Nat.succ i) hi
[PROOFSTEP]
rfl
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : Fin (length L)
⊢ drop (sum (take (↑i) (map length L))) (take (sum (take (↑i + 1) (map length L))) (join L)) = get L i
[PROOFSTEP]
have : (L.map length).take i = ((L.take (i + 1)).map length).take i := by simp [map_take, take_take]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : Fin (length L)
⊢ take (↑i) (map length L) = take (↑i) (map length (take (↑i + 1) L))
[PROOFSTEP]
simp [map_take, take_take]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : Fin (length L)
this : take (↑i) (map length L) = take (↑i) (map length (take (↑i + 1) L))
⊢ drop (sum (take (↑i) (map length L))) (take (sum (take (↑i + 1) (map length L))) (join L)) = get L i
[PROOFSTEP]
simp only [this, length_map, take_sum_join, drop_sum_join, drop_take_succ_eq_cons_get, join, append_nil]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : ℕ
hi : i < length L
⊢ drop (sum (take i (map length L))) (take (sum (take (i + 1) (map length L))) (join L)) = nthLe L i hi
[PROOFSTEP]
have : (L.map length).take i = ((L.take (i + 1)).map length).take i := by simp [map_take, take_take]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : ℕ
hi : i < length L
⊢ take i (map length L) = take i (map length (take (i + 1) L))
[PROOFSTEP]
simp [map_take, take_take]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i : ℕ
hi : i < length L
this : take i (map length L) = take i (map length (take (i + 1) L))
⊢ drop (sum (take i (map length L))) (take (sum (take (i + 1) (map length L))) (join L)) = nthLe L i hi
[PROOFSTEP]
simp [take_sum_join, this, drop_sum_join, drop_take_succ_eq_cons_nthLe _ hi]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
⊢ sum (take i (map length L)) + j < sum (take (i + 1) (map length L))
[PROOFSTEP]
simp [hi, sum_take_succ, hj]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
⊢ sum (take i (map length L)) + j < length (join L)
[PROOFSTEP]
convert lt_of_lt_of_le (sum_take_map_length_lt1 L hi hj) (monotone_sum_take _ hi)
[GOAL]
case h.e'_4
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
⊢ length (join L) = (fun i => sum (take i (map length L))) (length L)
[PROOFSTEP]
have : L.length = (L.map length).length := by simp
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
⊢ length L = length (map length L)
[PROOFSTEP]
simp
[GOAL]
case h.e'_4
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
this : length L = length (map length L)
⊢ length (join L) = (fun i => sum (take i (map length L))) (length L)
[PROOFSTEP]
simp [this, -length_map]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
⊢ nthLe (join L) (sum (take i (map length L)) + j) (_ : sum (take i (map length L)) + j < length (join L)) =
    nthLe (nthLe L i hi) j hj
[PROOFSTEP]
have := nthLe_take L.join (sum_take_map_length_lt2 L hi hj) (sum_take_map_length_lt1 L hi hj)
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
i j : ℕ
hi : i < length L
hj : j < length (nthLe L i hi)
this :
  nthLe (join L) (sum (take i (map length L)) + j) (_ : sum (take i (map length L)) + j < length (join L)) =
    nthLe (take (sum (take (i + 1) (map length L))) (join L)) (sum (take i (map length L)) + j)
      (_ : sum (take i (map length L)) + j < length (take (sum (take (i + 1) (map length L))) (join L)))
⊢ nthLe (join L) (sum (take i (map length L)) + j) (_ : sum (take i (map length L)) + j < length (join L)) =
    nthLe (nthLe L i hi) j hj
[PROOFSTEP]
rw [this, nthLe_drop, nthLe_of_eq (drop_take_succ_join_eq_nthLe L hi)]
[GOAL]
α : Type u_1
β : Type u_2
L L' : List (List α)
⊢ L = L' ↔ join L = join L' ∧ map length L = map length L'
[PROOFSTEP]
refine' ⟨fun H => by simp [H], _⟩
[GOAL]
α : Type u_1
β : Type u_2
L L' : List (List α)
H : L = L'
⊢ join L = join L' ∧ map length L = map length L'
[PROOFSTEP]
simp [H]
[GOAL]
α : Type u_1
β : Type u_2
L L' : List (List α)
⊢ join L = join L' ∧ map length L = map length L' → L = L'
[PROOFSTEP]
rintro ⟨join_eq, length_eq⟩
[GOAL]
case intro
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
⊢ L = L'
[PROOFSTEP]
apply ext_get
[GOAL]
case intro.hl
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
⊢ length L = length L'
[PROOFSTEP]
have : length (map length L) = length (map length L') := by rw [length_eq]
[GOAL]
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
⊢ length (map length L) = length (map length L')
[PROOFSTEP]
rw [length_eq]
[GOAL]
case intro.hl
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
this : length (map length L) = length (map length L')
⊢ length L = length L'
[PROOFSTEP]
simpa using this
[GOAL]
case intro.h
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
⊢ ∀ (n : ℕ) (h₁ : n < length L) (h₂ : n < length L'), get L { val := n, isLt := h₁ } = get L' { val := n, isLt := h₂ }
[PROOFSTEP]
intro n h₁ h₂
[GOAL]
case intro.h
α : Type u_1
β : Type u_2
L L' : List (List α)
join_eq : join L = join L'
length_eq : map length L = map length L'
n : ℕ
h₁ : n < length L
h₂ : n < length L'
⊢ get L { val := n, isLt := h₁ } = get L' { val := n, isLt := h₂ }
[PROOFSTEP]
rw [← drop_take_succ_join_eq_get, ← drop_take_succ_join_eq_get, join_eq, length_eq]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
h : L ≠ []
⊢ join (drop (length L - 1) L) = getLast L h
[PROOFSTEP]
induction L using List.reverseRecOn
[GOAL]
case H0
α : Type u_1
β : Type u_2
h : [] ≠ []
⊢ join (drop (length [] - 1) []) = getLast [] h
[PROOFSTEP]
cases h rfl
[GOAL]
case H1
α : Type u_1
β : Type u_2
l✝ : List (List α)
a✝¹ : List α
a✝ : ∀ (h : l✝ ≠ []), join (drop (length l✝ - 1) l✝) = getLast l✝ h
h : l✝ ++ [a✝¹] ≠ []
⊢ join (drop (length (l✝ ++ [a✝¹]) - 1) (l✝ ++ [a✝¹])) = getLast (l✝ ++ [a✝¹]) h
[PROOFSTEP]
simp
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
x : List α
⊢ x ++ join (map (fun l => l ++ x) L) = join (map (fun l => x ++ l) L) ++ x
[PROOFSTEP]
induction' L with _ _ ih
[GOAL]
case nil
α : Type u_1
β : Type u_2
x : List α
⊢ x ++ join (map (fun l => l ++ x) []) = join (map (fun l => x ++ l) []) ++ x
[PROOFSTEP]
rw [map_nil, join, append_nil, map_nil, join, nil_append]
[GOAL]
case cons
α : Type u_1
β : Type u_2
x head✝ : List α
tail✝ : List (List α)
ih : x ++ join (map (fun l => l ++ x) tail✝) = join (map (fun l => x ++ l) tail✝) ++ x
⊢ x ++ join (map (fun l => l ++ x) (head✝ :: tail✝)) = join (map (fun l => x ++ l) (head✝ :: tail✝)) ++ x
[PROOFSTEP]
rw [map_cons, join, map_cons, join, append_assoc, ih, append_assoc, append_assoc]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
⊢ reverse (join L) = join (reverse (map reverse L))
[PROOFSTEP]
induction' L with _ _ ih
[GOAL]
case nil
α : Type u_1
β : Type u_2
⊢ reverse (join []) = join (reverse (map reverse []))
[PROOFSTEP]
rfl
[GOAL]
case cons
α : Type u_1
β : Type u_2
head✝ : List α
tail✝ : List (List α)
ih : reverse (join tail✝) = join (reverse (map reverse tail✝))
⊢ reverse (join (head✝ :: tail✝)) = join (reverse (map reverse (head✝ :: tail✝)))
[PROOFSTEP]
rw [join, reverse_append, ih, map_cons, reverse_cons', join_concat]
[GOAL]
α : Type u_1
β : Type u_2
L : List (List α)
⊢ join (reverse L) = reverse (join (map reverse L))
[PROOFSTEP]
simpa [reverse_reverse, map_reverse] using congr_arg List.reverse (reverse_join L.reverse)


[GOAL]
⊢ SuccOrder (Fin 0)
[PROOFSTEP]
constructor
[GOAL]
case le_succ
⊢ ∀ (a : Fin 0), a ≤ ?succ a
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case le_succ
⊢ ∀ (a : Fin 0), a ≤ ?succ a
[PROOFSTEP]
assumption
[GOAL]
case le_succ
⊢ ∀ (a : Fin 0), a ≤ ?succ a
[PROOFSTEP]
intro a
[GOAL]
case le_succ
a : Fin 0
⊢ a ≤ ?succ a
[PROOFSTEP]
exact elim0 a
[GOAL]
case max_of_succ_le
⊢ ∀ {a : Fin 0}, ?succ a ≤ a → IsMax a
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case max_of_succ_le
⊢ ∀ {a : Fin 0}, ?succ a ≤ a → IsMax a
[PROOFSTEP]
assumption
[GOAL]
case max_of_succ_le
⊢ ∀ {a : Fin 0}, ?succ a ≤ a → IsMax a
[PROOFSTEP]
intro a
[GOAL]
case max_of_succ_le
a : Fin 0
⊢ ?succ a ≤ a → IsMax a
[PROOFSTEP]
exact elim0 a
[GOAL]
case succ_le_of_lt
⊢ ∀ {a b : Fin 0}, a < b → ?succ a ≤ b
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case succ_le_of_lt
⊢ ∀ {a b : Fin 0}, a < b → ?succ a ≤ b
[PROOFSTEP]
assumption
[GOAL]
case succ_le_of_lt
⊢ ∀ {a b : Fin 0}, a < b → ?succ a ≤ b
[PROOFSTEP]
intro a
[GOAL]
case succ_le_of_lt
a : Fin 0
⊢ ∀ {b : Fin 0}, a < b → ?succ a ≤ b
[PROOFSTEP]
exact elim0 a
[GOAL]
case le_of_lt_succ
⊢ ∀ {a b : Fin 0}, a < ?succ b → a ≤ b
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case le_of_lt_succ
⊢ ∀ {a b : Fin 0}, a < ?succ b → a ≤ b
[PROOFSTEP]
assumption
[GOAL]
case le_of_lt_succ
⊢ ∀ {a b : Fin 0}, a < ?succ b → a ≤ b
[PROOFSTEP]
intro a
[GOAL]
case le_of_lt_succ
a : Fin 0
⊢ ∀ {b : Fin 0}, a < ?succ b → a ≤ b
[PROOFSTEP]
exact elim0 a
[GOAL]
case succ
⊢ Fin 0 → Fin 0
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case succ
⊢ Fin 0 → Fin 0
[PROOFSTEP]
assumption
[GOAL]
case succ
⊢ Fin 0 → Fin 0
[PROOFSTEP]
intro a
[GOAL]
case succ
a : Fin 0
⊢ Fin 0
[PROOFSTEP]
exact elim0 a
[GOAL]
n : ℕ
⊢ ∀ {a : Fin (n + 1)}, ¬IsMax a → ∀ (b : Fin (n + 1)), a < b ↔ (fun i => if i < last n then i + 1 else i) a ≤ b
[PROOFSTEP]
intro a ha b
[GOAL]
n : ℕ
a : Fin (n + 1)
ha : ¬IsMax a
b : Fin (n + 1)
⊢ a < b ↔ (fun i => if i < last n then i + 1 else i) a ≤ b
[PROOFSTEP]
rw [isMax_iff_eq_top, eq_top_iff, not_le, top_eq_last] at ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMax a
ha : a < last n
b : Fin (n + 1)
⊢ a < b ↔ (fun i => if i < last n then i + 1 else i) a ≤ b
[PROOFSTEP]
dsimp
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMax a
ha : a < last n
b : Fin (n + 1)
⊢ a < b ↔ (if a < last n then a + 1 else a) ≤ b
[PROOFSTEP]
rw [if_pos ha, lt_iff_val_lt_val, le_iff_val_le_val, val_add_one_of_lt ha]
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMax a
ha : a < last n
b : Fin (n + 1)
⊢ ↑a < ↑b ↔ ↑a + 1 ≤ ↑b
[PROOFSTEP]
exact Nat.lt_iff_add_one_le
[GOAL]
n : ℕ
⊢ ∀ (a : Fin (n + 1)), IsMax a → (fun i => if i < last n then i + 1 else i) a = a
[PROOFSTEP]
intro a ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha : IsMax a
⊢ (fun i => if i < last n then i + 1 else i) a = a
[PROOFSTEP]
rw [isMax_iff_eq_top, top_eq_last] at ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : IsMax a
ha : a = last n
⊢ (fun i => if i < last n then i + 1 else i) a = a
[PROOFSTEP]
dsimp
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : IsMax a
ha : a = last n
⊢ (if a < last n then a + 1 else a) = a
[PROOFSTEP]
rw [if_neg ha.not_lt]
[GOAL]
⊢ PredOrder (Fin 0)
[PROOFSTEP]
constructor
[GOAL]
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a
[PROOFSTEP]
assumption
[GOAL]
case pred_le
⊢ ∀ (a : Fin 0), ?pred a ≤ a
[PROOFSTEP]
intro a
[GOAL]
case pred_le
a : Fin 0
⊢ ?pred a ≤ a
[PROOFSTEP]
exact elim0 a
[GOAL]
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a
[PROOFSTEP]
assumption
[GOAL]
case min_of_le_pred
⊢ ∀ {a : Fin 0}, a ≤ ?pred a → IsMin a
[PROOFSTEP]
intro a
[GOAL]
case min_of_le_pred
a : Fin 0
⊢ a ≤ ?pred a → IsMin a
[PROOFSTEP]
exact elim0 a
[GOAL]
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b
[PROOFSTEP]
assumption
[GOAL]
case le_pred_of_lt
⊢ ∀ {a b : Fin 0}, a < b → a ≤ ?pred b
[PROOFSTEP]
intro a
[GOAL]
case le_pred_of_lt
a : Fin 0
⊢ ∀ {b : Fin 0}, a < b → a ≤ ?pred b
[PROOFSTEP]
exact elim0 a
[GOAL]
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b
[PROOFSTEP]
assumption
[GOAL]
case le_of_pred_lt
⊢ ∀ {a b : Fin 0}, ?pred a < b → a ≤ b
[PROOFSTEP]
intro a
[GOAL]
case le_of_pred_lt
a : Fin 0
⊢ ∀ {b : Fin 0}, ?pred a < b → a ≤ b
[PROOFSTEP]
exact elim0 a
[GOAL]
case pred
⊢ Fin 0 → Fin 0
[PROOFSTEP]
first
| assumption
| intro a; exact elim0 a
[GOAL]
case pred
⊢ Fin 0 → Fin 0
[PROOFSTEP]
assumption
[GOAL]
case pred
⊢ Fin 0 → Fin 0
[PROOFSTEP]
intro a
[GOAL]
case pred
a : Fin 0
⊢ Fin 0
[PROOFSTEP]
exact elim0 a
[GOAL]
n : ℕ
⊢ ∀ {a : Fin (n + 1)}, ¬IsMin a → ∀ (b : Fin (n + 1)), b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a
[PROOFSTEP]
intro a ha b
[GOAL]
n : ℕ
a : Fin (n + 1)
ha : ¬IsMin a
b : Fin (n + 1)
⊢ b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a
[PROOFSTEP]
rw [isMin_iff_eq_bot, eq_bot_iff, not_le, bot_eq_zero] at ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMin a
ha : 0 < a
b : Fin (n + 1)
⊢ b ≤ (fun x => if x = 0 then 0 else x - 1) a ↔ b < a
[PROOFSTEP]
dsimp
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMin a
ha : 0 < a
b : Fin (n + 1)
⊢ (b ≤ if a = 0 then 0 else a - 1) ↔ b < a
[PROOFSTEP]
rw [if_neg ha.ne', lt_iff_val_lt_val, le_iff_val_le_val, coe_sub_one, if_neg ha.ne', le_tsub_iff_right, Iff.comm]
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMin a
ha : 0 < a
b : Fin (n + 1)
⊢ ↑b < ↑a ↔ ↑b + 1 ≤ ↑a
n : ℕ a : Fin (n + 1) ha✝ : ¬IsMin a ha : 0 < a b : Fin (n + 1) ⊢ 1 ≤ ↑a
[PROOFSTEP]
exact Nat.lt_iff_add_one_le
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : ¬IsMin a
ha : 0 < a
b : Fin (n + 1)
⊢ 1 ≤ ↑a
[PROOFSTEP]
exact ha
[GOAL]
n : ℕ
⊢ ∀ (a : Fin (n + 1)), IsMin a → (fun x => if x = 0 then 0 else x - 1) a = a
[PROOFSTEP]
intro a ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha : IsMin a
⊢ (fun x => if x = 0 then 0 else x - 1) a = a
[PROOFSTEP]
rw [isMin_iff_eq_bot, bot_eq_zero] at ha
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : IsMin a
ha : a = 0
⊢ (fun x => if x = 0 then 0 else x - 1) a = a
[PROOFSTEP]
dsimp
[GOAL]
n : ℕ
a : Fin (n + 1)
ha✝ : IsMin a
ha : a = 0
⊢ (if a = 0 then 0 else a - 1) = a
[PROOFSTEP]
rwa [if_pos ha, eq_comm]