Theorem: Nat.roughNumbersUpTo_eq_biUnion
File: Mathlib/NumberTheory/SmoothNumbers.lean

Proof steps:
state_before: N k : ℕ
⊢ N.roughNumbersUpTo k =
    (N.succ.primesBelow \ k.primesBelow).biUnion fun p => Finset.filter (fun m => m ≠ 0 ∧ p ∣ m) (Finset.range N.succ)
state_after: case a
N k m : ℕ
⊢ m ∈ N.roughNumbersUpTo k ↔
    m ∈
      (N.succ.primesBelow \ k.primesBelow).biUnion fun p => Finset.filter (fun m => m ≠ 0 ∧ p ∣ m) (Finset.range N.succ)
tactic: ext m
state_before: case a
N k m : ℕ
⊢ m ∈ N.roughNumbersUpTo k ↔
    m ∈
      (N.succ.primesBelow \ k.primesBelow).biUnion fun p => Finset.filter (fun m => m ≠ 0 ∧ p ∣ m) (Finset.range N.succ)
state_after: case a
N k m : ℕ
⊢ (m < N.succ ∧ m ≠ 0 ∧ ∃ x ≤ m, Prime x ∧ x ∣ m ∧ k ≤ x) ↔
    ∃ a, ((a < N.succ ∧ Prime a) ∧ (a < k → ¬Prime a)) ∧ m < N.succ ∧ m ≠ 0 ∧ a ∣ m
tactic: simp only [roughNumbersUpTo, mem_smoothNumbers_iff_forall_le, not_and, not_forall,
    not_lt, exists_prop, exists_and_left, Finset.mem_range, not_le, Finset.mem_filter,
    Finset.filter_congr_decidable, Finset.mem_biUnion, Finset.mem_sdiff, mem_primesBelow,
    show ∀ P Q : Prop, P ∧ (P → Q) ↔ P ∧ Q by tauto]
state_before: case a
N k m : ℕ
⊢ (m < N.succ ∧ m ≠ 0 ∧ ∃ x ≤ m, Prime x ∧ x ∣ m ∧ k ≤ x) ↔
    ∃ a, ((a < N.succ ∧ Prime a) ∧ (a < k → ¬Prime a)) ∧ m < N.succ ∧ m ≠ 0 ∧ a ∣ m
state_after: case a
N k m : ℕ
⊢ (∃ x, m < N.succ ∧ m ≠ 0 ∧ ¬m < x ∧ Prime x ∧ x ∣ m ∧ ¬x < k) ↔
    ∃ a, ((a < N.succ ∧ Prime a) ∧ (a < k → ¬Prime a)) ∧ m < N.succ ∧ m ≠ 0 ∧ a ∣ m
tactic: simp_rw [← exists_and_left, ← not_lt]
state_before: case a
N k m : ℕ
⊢ (∃ x, m < N.succ ∧ m ≠ 0 ∧ ¬m < x ∧ Prime x ∧ x ∣ m ∧ ¬x < k) ↔
    ∃ a, ((a < N.succ ∧ Prime a) ∧ (a < k → ¬Prime a)) ∧ m < N.succ ∧ m ≠ 0 ∧ a ∣ m
state_after: case a
N k m p : ℕ
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
tactic: refine exists_congr fun p ↦ ?_
state_before: case a
N k m p : ℕ
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
state_after: case a
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
tactic: have H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ :=
    fun h₁ h₂ h₃ ↦ (le_of_dvd (Nat.pos_of_ne_zero h₁) h₂).trans_lt h₃
state_before: case a
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
state_after: case a
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
H₂ : m ≠ 0 → p ∣ m → ¬m < p
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
tactic: have H₂ : m ≠ 0 → p ∣ m → ¬ m < p :=
    fun h₁ h₂ ↦ not_lt.mpr <| le_of_dvd (Nat.pos_of_ne_zero h₁) h₂
state_before: case a
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
H₂ : m ≠ 0 → p ∣ m → ¬m < p
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k ↔
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m
state_after: case a.mp
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
H₂ : m ≠ 0 → p ∣ m → ¬m < p
⊢ m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k →
    ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m

case a.mpr
N k m p : ℕ
H₁ : m ≠ 0 → p ∣ m → m < N.succ → p < N.succ
H₂ : m ≠ 0 → p ∣ m → ¬m < p
⊢ ((p < N.succ ∧ Prime p) ∧ (p < k → ¬Prime p)) ∧ m < N.succ ∧ m ≠ 0 ∧ p ∣ m →
    m < N.succ ∧ m ≠ 0 ∧ ¬m < p ∧ Prime p ∧ p ∣ m ∧ ¬p < k
tactic: constructor