l3lab/ntp-mathlib huggingface dataset:
/-- Every topological group in which there exists a compact set with nonempty interior
is weakly locally compact. -/
@[to_additive
  "Every separated topological additive group
  in which there exists a compact set with nonempty interior is weakly locally compact."]
theorem TopologicalSpace.PositiveCompacts.weaklyLocallyCompactSpace_of_group
    (K : PositiveCompacts G) : WeaklyLocallyCompactSpace G where
  exists_compact_mem_nhds x := by
    obtain ⟨y, hy⟩ := K.interior_nonempty
    refine ⟨(x * y⁻¹) • (K : Set G), K.isCompact.smul _, ?_⟩
    

Proof state:
case intro
α : Type u
β : Type v
G : Type w
H : Type x
inst✝² : TopologicalSpace G
inst✝¹ : Group G
inst✝ : TopologicalGroup G
K : PositiveCompacts G
x y : G
hy : y ∈ interior ↑K
⊢ (x * y⁻¹) • ↑K ∈ 𝓝 x

Next tactic:
rw [mem_interior_iff_mem_nhds] at hy
/-- Every topological group in which there exists a compact set with nonempty interior
is weakly locally compact. -/
@[to_additive
  "Every separated topological additive group
  in which there exists a compact set with nonempty interior is weakly locally compact."]
theorem TopologicalSpace.PositiveCompacts.weaklyLocallyCompactSpace_of_group
    (K : PositiveCompacts G) : WeaklyLocallyCompactSpace G where
  exists_compact_mem_nhds x := by
    obtain ⟨y, hy⟩ := K.interior_nonempty
    refine ⟨(x * y⁻¹) • (K : Set G), K.isCompact.smul _, ?_⟩
    rw [mem_interior_iff_mem_nhds] at hy
    

Proof state:
case intro
α : Type u
β : Type v
G : Type w
H : Type x
inst✝² : TopologicalSpace G
inst✝¹ : Group G
inst✝ : TopologicalGroup G
K : PositiveCompacts G
x y : G
hy : ↑K ∈ 𝓝 y
⊢ (x * y⁻¹) • ↑K ∈ 𝓝 x

Next tactic:
simpa using smul_mem_nhds (x * y⁻¹) hy
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    

Proof state:
α : Type u
β : Type v
G : Type w
H : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
⊢ Continuous fun p => p.1 • p.2

Next tactic:
let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
    

Proof state:
α : Type u
β : Type v
G : Type w
H : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
⊢ Continuous fun p => p.1 • p.2

Next tactic:
change Continuous F
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
    change Continuous F
    

Proof state:
α : Type u
β : Type v
G : Type w
H : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
⊢ Continuous F

Next tactic:
have H : Continuous (F ∘ fun p : G × G => (p.1, QuotientGroup.mk p.2)) := by
      change Continuous fun p : G × G => QuotientGroup.mk (p.1 * p.2)
      refine' continuous_coinduced_rng.comp continuous_mul
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
    change Continuous F
    have H : Continuous (F ∘ fun p : G × G => (p.1, QuotientGroup.mk p.2)) := by
      

Proof state:
α : Type u
β : Type v
G : Type w
H : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
⊢ Continuous (F ∘ fun p => (p.1, ↑p.2))

Next tactic:
change Continuous fun p : G × G => QuotientGroup.mk (p.1 * p.2)
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
    change Continuous F
    have H : Continuous (F ∘ fun p : G × G => (p.1, QuotientGroup.mk p.2)) := by
      change Continuous fun p : G × G => QuotientGroup.mk (p.1 * p.2)
      

Proof state:
α : Type u
β : Type v
G : Type w
H : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
⊢ Continuous fun p => ↑(p.1 * p.2)

Next tactic:
refine' continuous_coinduced_rng.comp continuous_mul
@[to_additive]
instance QuotientGroup.continuousSMul [LocallyCompactSpace G] : ContinuousSMul G (G ⧸ Γ) where
  continuous_smul := by
    let F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
    change Continuous F
    have H : Continuous (F ∘ fun p : G × G => (p.1, QuotientGroup.mk p.2)) := by
      change Continuous fun p : G × G => QuotientGroup.mk (p.1 * p.2)
      refine' continuous_coinduced_rng.comp continuous_mul
    

Proof state:
α : Type u
β : Type v
G : Type w
H✝ : Type x
inst✝³ : Group G
inst✝² : TopologicalSpace G
inst✝¹ : TopologicalGroup G
Γ : Subgroup G
inst✝ : LocallyCompactSpace G
F : G × G ⧸ Γ → G ⧸ Γ := fun p => p.1 • p.2
H : Continuous (F ∘ fun p => (p.1, ↑p.2))
⊢ Continuous F

Next tactic:
exact QuotientMap.continuous_lift_prod_right quotientMap_quotient_mk' H
@[simp]
lemma primesBelow_zero : primesBelow 0 = ∅ := by
  

Proof state:
⊢ primesBelow 0 = ∅

Next tactic:
rw [primesBelow, Finset.range_zero, Finset.filter_empty]
lemma primesBelow_succ (n : ℕ) :
    primesBelow n.succ = if n.Prime then insert n (primesBelow n) else primesBelow n := by
  

Proof state:
n : ℕ
⊢ primesBelow (succ n) = if Prime n then insert n (primesBelow n) else primesBelow n

Next tactic:
rw [primesBelow, primesBelow, Finset.range_succ, Finset.filter_insert]
/-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n := by
  

Proof state:
n m : ℕ
⊢ m ∈ smoothNumbers n ↔ ∀ (p : ℕ), Prime p → p ∣ m → p < n

Next tactic:
rw [mem_smoothNumbers]
/-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n := by
  rw [mem_smoothNumbers]
  

Proof state:
n m : ℕ
⊢ (m ≠ 0 ∧ ∀ p ∈ factors m, p < n) ↔ ∀ (p : ℕ), Prime p → p ∣ m → p < n

Next tactic:
refine ⟨fun H p hp h ↦ H.2 p <| (mem_factors_iff_dvd H.1 hp).mpr h,
          fun H ↦ ⟨?_, fun p hp ↦ H p (prime_of_mem_factors hp) (dvd_of_mem_factors hp)⟩⟩
/-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n := by
  rw [mem_smoothNumbers]
  refine ⟨fun H p hp h ↦ H.2 p <| (mem_factors_iff_dvd H.1 hp).mpr h,
          fun H ↦ ⟨?_, fun p hp ↦ H p (prime_of_mem_factors hp) (dvd_of_mem_factors hp)⟩⟩
  

Proof state:
n m : ℕ
H : ∀ (p : ℕ), Prime p → p ∣ m → p < n
⊢ m ≠ 0

Next tactic:
rintro rfl
/-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n := by
  rw [mem_smoothNumbers]
  refine ⟨fun H p hp h ↦ H.2 p <| (mem_factors_iff_dvd H.1 hp).mpr h,
          fun H ↦ ⟨?_, fun p hp ↦ H p (prime_of_mem_factors hp) (dvd_of_mem_factors hp)⟩⟩
  rintro rfl
  

Proof state:
n : ℕ
H : ∀ (p : ℕ), Prime p → p ∣ 0 → p < n
⊢ False

Next tactic:
obtain ⟨p, hp₁, hp₂⟩ := exists_infinite_primes n
/-- `m` is `n`-smooth if and only if all prime divisors of `m` are less than `n`. -/
lemma mem_smoothNumbers' {n m : ℕ} : m ∈ smoothNumbers n ↔ ∀ p, p.Prime → p ∣ m → p < n := by
  rw [mem_smoothNumbers]
  refine ⟨fun H p hp h ↦ H.2 p <| (mem_factors_iff_dvd H.1 hp).mpr h,
          fun H ↦ ⟨?_, fun p hp ↦ H p (prime_of_mem_factors hp) (dvd_of_mem_factors hp)⟩⟩
  rintro rfl
  obtain ⟨p, hp₁, hp₂⟩ := exists_infinite_primes n
  

Proof state:
case intro.intro
n : ℕ
H : ∀ (p : ℕ), Prime p → p ∣ 0 → p < n
p : ℕ
hp₁ : n ≤ p
hp₂ : Prime p
⊢ False

Next tactic:
exact ((H p hp₂ <| dvd_zero _).trans_le hp₁).false
@[simp]
lemma smoothNumbers_zero : smoothNumbers 0 = {1} := by
  

Proof state:
⊢ smoothNumbers 0 = {1}

Next tactic:
ext m
@[simp]
lemma smoothNumbers_zero : smoothNumbers 0 = {1} := by
  ext m
  

Proof state:
case h
m : ℕ
⊢ m ∈ smoothNumbers 0 ↔ m ∈ {1}

Next tactic:
rw [Set.mem_singleton_iff, mem_smoothNumbers]
@[simp]
lemma smoothNumbers_zero : smoothNumbers 0 = {1} := by
  ext m
  rw [Set.mem_singleton_iff, mem_smoothNumbers]
  

Proof state:
case h
m : ℕ
⊢ (m ≠ 0 ∧ ∀ p ∈ factors m, p < 0) ↔ m = 1

Next tactic:
simp_rw [not_lt_zero]
@[simp]
lemma smoothNumbers_zero : smoothNumbers 0 = {1} := by
  ext m
  rw [Set.mem_singleton_iff, mem_smoothNumbers]
  simp_rw [not_lt_zero]
  

Proof state:
case h
m : ℕ
⊢ (m ≠ 0 ∧ ∀ p ∈ factors m, False) ↔ m = 1

Next tactic:
rw [← List.eq_nil_iff_forall_not_mem, factors_eq_nil, and_or_left, not_and_self_iff, false_or,
    ne_and_eq_iff_right zero_ne_one]
/-- The product of the prime factors of `n` that are less than `N` is an `N`-smooth number. -/
lemma prod_mem_smoothNumbers (n N : ℕ) : (n.factors.filter (· < N)).prod ∈ smoothNumbers N := by
  

Proof state:
n N : ℕ
⊢ List.prod (List.filter (fun x => decide (x < N)) (factors n)) ∈ smoothNumbers N

Next tactic:
have h₀ : (n.factors.filter (· < N)).prod ≠ 0 :=
    List.prod_ne_zero fun h ↦ (pos_of_mem_factors (List.mem_of_mem_filter h)).false
/-- The product of the prime factors of `n` that are less than `N` is an `N`-smooth number. -/
lemma prod_mem_smoothNumbers (n N : ℕ) : (n.factors.filter (· < N)).prod ∈ smoothNumbers N := by
  have h₀ : (n.factors.filter (· < N)).prod ≠ 0 :=
    List.prod_ne_zero fun h ↦ (pos_of_mem_factors (List.mem_of_mem_filter h)).false
  

Proof state:
n N : ℕ
h₀ : List.prod (List.filter (fun x => decide (x < N)) (factors n)) ≠ 0
⊢ List.prod (List.filter (fun x => decide (x < N)) (factors n)) ∈ smoothNumbers N

Next tactic:
refine ⟨h₀, fun p hp ↦ ?_⟩
/-- The product of the prime factors of `n` that are less than `N` is an `N`-smooth number. -/
lemma prod_mem_smoothNumbers (n N : ℕ) : (n.factors.filter (· < N)).prod ∈ smoothNumbers N := by
  have h₀ : (n.factors.filter (· < N)).prod ≠ 0 :=
    List.prod_ne_zero fun h ↦ (pos_of_mem_factors (List.mem_of_mem_filter h)).false
  refine ⟨h₀, fun p hp ↦ ?_⟩
  

Proof state:
n N : ℕ
h₀ : List.prod (List.filter (fun x => decide (x < N)) (factors n)) ≠ 0
p : ℕ
hp : p ∈ factors (List.prod (List.filter (fun x => decide (x < N)) (factors n)))
⊢ p < N

Next tactic:
obtain ⟨H₁, H₂⟩ := (mem_factors h₀).mp hp
/-- The product of the prime factors of `n` that are less than `N` is an `N`-smooth number. -/
lemma prod_mem_smoothNumbers (n N : ℕ) : (n.factors.filter (· < N)).prod ∈ smoothNumbers N := by
  have h₀ : (n.factors.filter (· < N)).prod ≠ 0 :=
    List.prod_ne_zero fun h ↦ (pos_of_mem_factors (List.mem_of_mem_filter h)).false
  refine ⟨h₀, fun p hp ↦ ?_⟩
  obtain ⟨H₁, H₂⟩ := (mem_factors h₀).mp hp
  

Proof state:
case intro
n N : ℕ
h₀ : List.prod (List.filter (fun x => decide (x < N)) (factors n)) ≠ 0
p : ℕ
hp : p ∈ factors (List.prod (List.filter (fun x => decide (x < N)) (factors n)))
H₁ : Prime p
H₂ : p ∣ List.prod (List.filter (fun x => decide (x < N)) (factors n))
⊢ p < N

Next tactic:
simpa only [decide_eq_true_eq] using List.of_mem_filter <| mem_list_primes_of_dvd_prod H₁.prime
    (fun _ hq ↦ (prime_of_mem_factors (List.mem_of_mem_filter hq)).prime) H₂
/-- The sets of `N`-smooth and of `(N+1)`-smooth numbers are the same when `N` is not prime.
See `Nat.equivProdNatSmoothNumbers` for when `N` is prime. -/
lemma smoothNumbers_succ {N : ℕ} (hN : ¬ N.Prime) : N.succ.smoothNumbers = N.smoothNumbers := by
  

Proof state:
N : ℕ
hN : ¬Prime N
⊢ smoothNumbers (succ N) = smoothNumbers N

Next tactic:
ext m
/-- The sets of `N`-smooth and of `(N+1)`-smooth numbers are the same when `N` is not prime.
See `Nat.equivProdNatSmoothNumbers` for when `N` is prime. -/
lemma smoothNumbers_succ {N : ℕ} (hN : ¬ N.Prime) : N.succ.smoothNumbers = N.smoothNumbers := by
  ext m
  

Proof state:
case h
N : ℕ
hN : ¬Prime N
m : ℕ
⊢ m ∈ smoothNumbers (succ N) ↔ m ∈ smoothNumbers N

Next tactic:
refine ⟨fun hm ↦ ⟨hm.1, fun p hp ↦ ?_⟩,
         fun hm ↦ ⟨hm.1, fun p hp ↦ (hm.2 p hp).trans <| lt.base N⟩⟩
/-- The sets of `N`-smooth and of `(N+1)`-smooth numbers are the same when `N` is not prime.
See `Nat.equivProdNatSmoothNumbers` for when `N` is prime. -/
lemma smoothNumbers_succ {N : ℕ} (hN : ¬ N.Prime) : N.succ.smoothNumbers = N.smoothNumbers := by
  ext m
  refine ⟨fun hm ↦ ⟨hm.1, fun p hp ↦ ?_⟩,
         fun hm ↦ ⟨hm.1, fun p hp ↦ (hm.2 p hp).trans <| lt.base N⟩⟩
  

Proof state:
case h
N : ℕ
hN : ¬Prime N
m : ℕ
hm : m ∈ smoothNumbers (succ N)
p : ℕ
hp : p ∈ factors m
⊢ p < N

Next tactic:
exact lt_of_le_of_ne (lt_succ.mp <| hm.2 p hp) fun h ↦ hN <| h ▸ prime_of_mem_factors hp
@[simp] lemma smoothNumbers_one : smoothNumbers 1 = {1} := by
  

Proof state:
⊢ smoothNumbers 1 = {1}

Next tactic:
simp (config := {decide := true}) [smoothNumbers_succ]
/-- The non-zero non-`N`-smooth numbers are `≥ N`. -/
lemma smoothNumbers_compl (N : ℕ) : (N.smoothNumbers)ᶜ \ {0} ⊆ {n | N ≤ n} := by
  

Proof state:
N : ℕ
⊢ (smoothNumbers N)ᶜ \ {0} ⊆ {n | N ≤ n}

Next tactic:
intro n hn
/-- The non-zero non-`N`-smooth numbers are `≥ N`. -/
lemma smoothNumbers_compl (N : ℕ) : (N.smoothNumbers)ᶜ \ {0} ⊆ {n | N ≤ n} := by
  intro n hn
  

Proof state:
N n : ℕ
hn : n ∈ (smoothNumbers N)ᶜ \ {0}
⊢ n ∈ {n | N ≤ n}

Next tactic:
simp only [Set.mem_compl_iff, mem_smoothNumbers, Set.mem_diff, ne_eq, not_and, not_forall,
    not_lt, exists_prop, Set.mem_singleton_iff] at hn
/-- The non-zero non-`N`-smooth numbers are `≥ N`. -/
lemma smoothNumbers_compl (N : ℕ) : (N.smoothNumbers)ᶜ \ {0} ⊆ {n | N ≤ n} := by
  intro n hn
  simp only [Set.mem_compl_iff, mem_smoothNumbers, Set.mem_diff, ne_eq, not_and, not_forall,
    not_lt, exists_prop, Set.mem_singleton_iff] at hn
  

Proof state:
N n : ℕ
hn : (¬n = 0 → ∃ x ∈ factors n, N ≤ x) ∧ ¬n = 0
⊢ n ∈ {n | N ≤ n}

Next tactic:
obtain ⟨m, hm₁, hm₂⟩ := hn.1 hn.2
/-- The non-zero non-`N`-smooth numbers are `≥ N`. -/
lemma smoothNumbers_compl (N : ℕ) : (N.smoothNumbers)ᶜ \ {0} ⊆ {n | N ≤ n} := by
  intro n hn
  simp only [Set.mem_compl_iff, mem_smoothNumbers, Set.mem_diff, ne_eq, not_and, not_forall,
    not_lt, exists_prop, Set.mem_singleton_iff] at hn
  obtain ⟨m, hm₁, hm₂⟩ := hn.1 hn.2
  

Proof state:
case intro.intro
N n : ℕ
hn : (¬n = 0 → ∃ x ∈ factors n, N ≤ x) ∧ ¬n = 0
m : ℕ
hm₁ : m ∈ factors n
hm₂ : N ≤ m
⊢ n ∈ {n | N ≤ n}

Next tactic:
exact hm₂.trans <| le_of_mem_factors hm₁
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  

Proof state:
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
⊢ p ^ e * n ∈ smoothNumbers (succ p)

Next tactic:
have hp' := pow_ne_zero e hp
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  have hp' := pow_ne_zero e hp
  

Proof state:
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
hp' : p ^ e ≠ 0
⊢ p ^ e * n ∈ smoothNumbers (succ p)

Next tactic:
refine ⟨mul_ne_zero hp' hn.1, fun q hq ↦ ?_⟩
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  have hp' := pow_ne_zero e hp
  refine ⟨mul_ne_zero hp' hn.1, fun q hq ↦ ?_⟩
  

Proof state:
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
hp' : p ^ e ≠ 0
q : ℕ
hq : q ∈ factors (p ^ e * n)
⊢ q < succ p

Next tactic:
rcases (mem_factors_mul hp' hn.1).mp hq with H | H
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  have hp' := pow_ne_zero e hp
  refine ⟨mul_ne_zero hp' hn.1, fun q hq ↦ ?_⟩
  rcases (mem_factors_mul hp' hn.1).mp hq with H | H
  · 

Proof state:
case inl
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
hp' : p ^ e ≠ 0
q : ℕ
hq : q ∈ factors (p ^ e * n)
H : q ∈ factors (p ^ e)
⊢ q < succ p

Next tactic:
rw [mem_factors hp'] at H
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  have hp' := pow_ne_zero e hp
  refine ⟨mul_ne_zero hp' hn.1, fun q hq ↦ ?_⟩
  rcases (mem_factors_mul hp' hn.1).mp hq with H | H
  · rw [mem_factors hp'] at H
    

Proof state:
case inl
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
hp' : p ^ e ≠ 0
q : ℕ
hq : q ∈ factors (p ^ e * n)
H : Prime q ∧ q ∣ p ^ e
⊢ q < succ p

Next tactic:
exact lt_succ.mpr <| le_of_dvd hp.bot_lt <| H.1.dvd_of_dvd_pow H.2
/-- If `p` is positive and `n` is `p`-smooth, then every product `p^e * n` is `(p+1)`-smooth. -/
lemma pow_mul_mem_smoothNumbers {p n : ℕ} (hp : p ≠ 0) (e : ℕ) (hn : n ∈ smoothNumbers p) :
    p ^ e * n ∈ smoothNumbers (succ p) := by
  have hp' := pow_ne_zero e hp
  refine ⟨mul_ne_zero hp' hn.1, fun q hq ↦ ?_⟩
  rcases (mem_factors_mul hp' hn.1).mp hq with H | H
  · rw [mem_factors hp'] at H
    exact lt_succ.mpr <| le_of_dvd hp.bot_lt <| H.1.dvd_of_dvd_pow H.2
  · 

Proof state:
case inr
p n : ℕ
hp : p ≠ 0
e : ℕ
hn : n ∈ smoothNumbers p
hp' : p ^ e ≠ 0
q : ℕ
hq : q ∈ factors (p ^ e * n)
H : q ∈ factors n
⊢ q < succ p

Next tactic:
exact (hn.2 q H).trans <| lt_succ_self p
/-- If `p` is a prime and `n` is `p`-smooth, then `p` and `n` are coprime. -/
lemma Prime.smoothNumbers_coprime {p n : ℕ} (hp : p.Prime) (hn : n ∈ smoothNumbers p) :
    Nat.Coprime p n := by
  

Proof state:
p n : ℕ
hp : Prime p
hn : n ∈ smoothNumbers p
⊢ Coprime p n

Next tactic:
rw [hp.coprime_iff_not_dvd, ← mem_factors_iff_dvd hn.1 hp]
/-- If `p` is a prime and `n` is `p`-smooth, then `p` and `n` are coprime. -/
lemma Prime.smoothNumbers_coprime {p n : ℕ} (hp : p.Prime) (hn : n ∈ smoothNumbers p) :
    Nat.Coprime p n := by
  rw [hp.coprime_iff_not_dvd, ← mem_factors_iff_dvd hn.1 hp]
  

Proof state:
p n : ℕ
hp : Prime p
hn : n ∈ smoothNumbers p
⊢ p ∉ factors n

Next tactic:
exact fun H ↦ (hn.2 p H).false
open List Perm in
/-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp: p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ where
  toFun := fun ⟨e, n⟩ ↦ ⟨p ^ e * n, pow_mul_mem_smoothNumbers hp.ne_zero e n.2⟩
  invFun := fun ⟨m, _⟩  ↦ (m.factorization p,
                            ⟨(m.factors.filter (· < p)).prod, prod_mem_smoothNumbers ..⟩)
  left_inv := by
    

Proof state:
p : ℕ
hp : Prime p
⊢ Function.LeftInverse
    (fun x =>
      match x with
      | { val := m, property := property } =>
        ((factorization m) p,
          { val := prod (List.filter (fun x => decide (x < p)) (factors m)),
            property := (_ : prod (List.filter (fun x => decide (x < p)) (factors m)) ∈ smoothNumbers p) }))
    fun x =>
    match x with
    | (e, n) => { val := p ^ e * ↑n, property := (_ : p ^ e * ↑n ∈ smoothNumbers (succ p)) }

Next tactic:
rintro ⟨e, m, hm₀, hm⟩
open List Perm in
/-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp: p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ where
  toFun := fun ⟨e, n⟩ ↦ ⟨p ^ e * n, pow_mul_mem_smoothNumbers hp.ne_zero e n.2⟩
  invFun := fun ⟨m, _⟩  ↦ (m.factorization p,
                            ⟨(m.factors.filter (· < p)).prod, prod_mem_smoothNumbers ..⟩)
  left_inv := by
    rintro ⟨e, m, hm₀, hm⟩
    

Proof state:
case mk.mk.intro
p : ℕ
hp : Prime p
e m : ℕ
hm₀ : m ≠ 0
hm : ∀ p_1 ∈ factors m, p_1 < p
⊢ (fun x =>
        match x with
        | { val := m, property := property } =>
          ((factorization m) p,
            { val := prod (List.filter (fun x => decide (x < p)) (factors m)),
              property := (_ : prod (List.filter (fun x => decide (x < p)) (factors m)) ∈ smoothNumbers p) }))
      ((fun x =>
          match x with
          | (e, n) => { val := p ^ e * ↑n, property := (_ : p ^ e * ↑n ∈ smoothNumbers (succ p)) })
        (e, { val := m, property := (_ : m ≠ 0 ∧ ∀ p_1 ∈ factors m, p_1 < p) })) =
    (e, { val := m, property := (_ : m ≠ 0 ∧ ∀ p_1 ∈ factors m, p_1 < p) })

Next tactic:
simp (config := { etaStruct := .all }) only
      [Set.coe_setOf, Set.mem_setOf_eq, Prod.mk.injEq, Subtype.mk.injEq]
open List Perm in
/-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp: p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ where
  toFun := fun ⟨e, n⟩ ↦ ⟨p ^ e * n, pow_mul_mem_smoothNumbers hp.ne_zero e n.2⟩
  invFun := fun ⟨m, _⟩  ↦ (m.factorization p,
                            ⟨(m.factors.filter (· < p)).prod, prod_mem_smoothNumbers ..⟩)
  left_inv := by
    rintro ⟨e, m, hm₀, hm⟩
    simp (config := { etaStruct := .all }) only
      [Set.coe_setOf, Set.mem_setOf_eq, Prod.mk.injEq, Subtype.mk.injEq]
    

Proof state:
case mk.mk.intro
p : ℕ
hp : Prime p
e m : ℕ
hm₀ : m ≠ 0
hm : ∀ p_1 ∈ factors m, p_1 < p
⊢ (factorization (p ^ e * m)) p = e ∧ prod (List.filter (fun x => decide (x < p)) (factors (p ^ e * m))) = m

Next tactic:
constructor
open List Perm in
/-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp: p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ where
  toFun := fun ⟨e, n⟩ ↦ ⟨p ^ e * n, pow_mul_mem_smoothNumbers hp.ne_zero e n.2⟩
  invFun := fun ⟨m, _⟩  ↦ (m.factorization p,
                            ⟨(m.factors.filter (· < p)).prod, prod_mem_smoothNumbers ..⟩)
  left_inv := by
    rintro ⟨e, m, hm₀, hm⟩
    simp (config := { etaStruct := .all }) only
      [Set.coe_setOf, Set.mem_setOf_eq, Prod.mk.injEq, Subtype.mk.injEq]
    constructor
    · 

Proof state:
case mk.mk.intro.left
p : ℕ
hp : Prime p
e m : ℕ
hm₀ : m ≠ 0
hm : ∀ p_1 ∈ factors m, p_1 < p
⊢ (factorization (p ^ e * m)) p = e

Next tactic:
rw [factorization_mul (pos_iff_ne_zero.mp <| pos_pow_of_pos e hp.pos) hm₀]
open List Perm in
/-- We establish the bijection from `ℕ × smoothNumbers p` to `smoothNumbers (p+1)`
given by `(e, n) ↦ p^e * n` when `p` is a prime. See `Nat.smoothNumbers_succ` for
when `p` is not prime. -/
def equivProdNatSmoothNumbers {p : ℕ} (hp: p.Prime) :
    ℕ × smoothNumbers p ≃ smoothNumbers p.succ where
  toFun := fun ⟨e, n⟩ ↦ ⟨p ^ e * n, pow_mul_mem_smoothNumbers hp.ne_zero e n.2⟩
  invFun := fun ⟨m, _⟩  ↦ (m.factorization p,
                            ⟨(m.factors.filter (· < p)).prod, prod_mem_smoothNumbers ..⟩)
  left_inv := by
    rintro ⟨e, m, hm₀, hm⟩
    simp (config := { etaStruct := .all }) only
      [Set.coe_setOf, Set.mem_setOf_eq, Prod.mk.injEq, Subtype.mk.injEq]
    constructor
    · rw [factorization_mul (pos_iff_ne_zero.mp <| pos_pow_of_pos e hp.pos) hm₀]
      

Proof state:
case mk.mk.intro.left
p : ℕ
hp : Prime p
e m : ℕ
hm₀ : m ≠ 0
hm : ∀ p_1 ∈ factors m, p_1 < p
⊢ (factorization (p ^ e) + factorization m) p = e

Next tactic:
simp only [factorization_pow, Finsupp.coe_add, Finsupp.coe_smul, nsmul_eq_mul,
        Pi.coe_nat, cast_id, Pi.add_apply, Pi.mul_apply, hp.factorization_self,
        mul_one, add_right_eq_self]