l3lab/ntp-mathlib huggingface dataset:
theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α]
    [∀ a : α, DecidablePred (Associated a)] {s : Multiset α} (n : α) (h : ∀ a ∈ s, Prime a)
    (div : ∀ a ∈ s, a ∣ n) (uniq : ∀ a, s.countP (Associated a) ≤ 1) : s.prod ∣ n := by
  induction' s using Multiset.induction_on with a s induct n primes divs generalizing n
  · simp only [Multiset.prod_zero, one_dvd]
  · rw [Multiset.prod_cons]
    obtain ⟨k, rfl⟩ : a ∣ n := div a (Multiset.mem_cons_self a s)
    apply mul_dvd_mul_left a
    refine induct _ (fun a ha => h a (Multiset.mem_cons_of_mem ha)) (fun b b_in_s => ?_)
      fun a => (Multiset.countP_le_of_le _ (Multiset.le_cons_self _ _)).trans (uniq a)
    · have b_div_n := div b (Multiset.mem_cons_of_mem b_in_s)
      have a_prime := h a (Multiset.mem_cons_self a s)
      have b_prime := h b (Multiset.mem_cons_of_mem b_in_s)
      refine' (b_prime.dvd_or_dvd b_div_n).resolve_left fun b_div_a => _
      have assoc := b_prime.associated_of_dvd a_prime b_div_a
      

Proof state:
case cons.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : (a : α) → DecidablePred (Associated a)
a : α
s : Multiset α
induct : ∀ (n : α), (∀ a ∈ s, Prime a) → (∀ a ∈ s, a ∣ n) → (∀ (a : α), countP (Associated a) s ≤ 1) → prod s ∣ n
h : ∀ a_1 ∈ a ::ₘ s, Prime a_1
uniq : ∀ (a_1 : α), countP (Associated a_1) (a ::ₘ s) ≤ 1
k : α
div : ∀ a_1 ∈ a ::ₘ s, a_1 ∣ a * k
b : α
b_in_s : b ∈ s
b_div_n : b ∣ a * k
a_prime : Prime a
b_prime : Prime b
b_div_a : b ∣ a
assoc : b ~ᵤ a
⊢ False

Next tactic:
have := uniq a
theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α]
    [∀ a : α, DecidablePred (Associated a)] {s : Multiset α} (n : α) (h : ∀ a ∈ s, Prime a)
    (div : ∀ a ∈ s, a ∣ n) (uniq : ∀ a, s.countP (Associated a) ≤ 1) : s.prod ∣ n := by
  induction' s using Multiset.induction_on with a s induct n primes divs generalizing n
  · simp only [Multiset.prod_zero, one_dvd]
  · rw [Multiset.prod_cons]
    obtain ⟨k, rfl⟩ : a ∣ n := div a (Multiset.mem_cons_self a s)
    apply mul_dvd_mul_left a
    refine induct _ (fun a ha => h a (Multiset.mem_cons_of_mem ha)) (fun b b_in_s => ?_)
      fun a => (Multiset.countP_le_of_le _ (Multiset.le_cons_self _ _)).trans (uniq a)
    · have b_div_n := div b (Multiset.mem_cons_of_mem b_in_s)
      have a_prime := h a (Multiset.mem_cons_self a s)
      have b_prime := h b (Multiset.mem_cons_of_mem b_in_s)
      refine' (b_prime.dvd_or_dvd b_div_n).resolve_left fun b_div_a => _
      have assoc := b_prime.associated_of_dvd a_prime b_div_a
      have := uniq a
      

Proof state:
case cons.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : (a : α) → DecidablePred (Associated a)
a : α
s : Multiset α
induct : ∀ (n : α), (∀ a ∈ s, Prime a) → (∀ a ∈ s, a ∣ n) → (∀ (a : α), countP (Associated a) s ≤ 1) → prod s ∣ n
h : ∀ a_1 ∈ a ::ₘ s, Prime a_1
uniq : ∀ (a_1 : α), countP (Associated a_1) (a ::ₘ s) ≤ 1
k : α
div : ∀ a_1 ∈ a ::ₘ s, a_1 ∣ a * k
b : α
b_in_s : b ∈ s
b_div_n : b ∣ a * k
a_prime : Prime a
b_prime : Prime b
b_div_a : b ∣ a
assoc : b ~ᵤ a
this : countP (Associated a) (a ::ₘ s) ≤ 1
⊢ False

Next tactic:
rw [Multiset.countP_cons_of_pos _ (Associated.refl _), Nat.succ_le_succ_iff, ← not_lt,
        Multiset.countP_pos] at this
theorem Multiset.prod_primes_dvd [CancelCommMonoidWithZero α]
    [∀ a : α, DecidablePred (Associated a)] {s : Multiset α} (n : α) (h : ∀ a ∈ s, Prime a)
    (div : ∀ a ∈ s, a ∣ n) (uniq : ∀ a, s.countP (Associated a) ≤ 1) : s.prod ∣ n := by
  induction' s using Multiset.induction_on with a s induct n primes divs generalizing n
  · simp only [Multiset.prod_zero, one_dvd]
  · rw [Multiset.prod_cons]
    obtain ⟨k, rfl⟩ : a ∣ n := div a (Multiset.mem_cons_self a s)
    apply mul_dvd_mul_left a
    refine induct _ (fun a ha => h a (Multiset.mem_cons_of_mem ha)) (fun b b_in_s => ?_)
      fun a => (Multiset.countP_le_of_le _ (Multiset.le_cons_self _ _)).trans (uniq a)
    · have b_div_n := div b (Multiset.mem_cons_of_mem b_in_s)
      have a_prime := h a (Multiset.mem_cons_self a s)
      have b_prime := h b (Multiset.mem_cons_of_mem b_in_s)
      refine' (b_prime.dvd_or_dvd b_div_n).resolve_left fun b_div_a => _
      have assoc := b_prime.associated_of_dvd a_prime b_div_a
      have := uniq a
      rw [Multiset.countP_cons_of_pos _ (Associated.refl _), Nat.succ_le_succ_iff, ← not_lt,
        Multiset.countP_pos] at this
      

Proof state:
case cons.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : (a : α) → DecidablePred (Associated a)
a : α
s : Multiset α
induct : ∀ (n : α), (∀ a ∈ s, Prime a) → (∀ a ∈ s, a ∣ n) → (∀ (a : α), countP (Associated a) s ≤ 1) → prod s ∣ n
h : ∀ a_1 ∈ a ::ₘ s, Prime a_1
uniq : ∀ (a_1 : α), countP (Associated a_1) (a ::ₘ s) ≤ 1
k : α
div : ∀ a_1 ∈ a ::ₘ s, a_1 ∣ a * k
b : α
b_in_s : b ∈ s
b_div_n : b ∣ a * k
a_prime : Prime a
b_prime : Prime b
b_div_a : b ∣ a
assoc : b ~ᵤ a
this : ¬∃ a_1 ∈ s, a ~ᵤ a_1
⊢ False

Next tactic:
exact this ⟨b, b_in_s, assoc.symm⟩
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
⊢ ∏ p in s, p ∣ n

Next tactic:
classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
          apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
          apply Multiset.nodup_iff_count_le_one.mp
          exact s.nodup)
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
⊢ ∏ p in s, p ∣ n

Next tactic:
exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
          apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
          apply Multiset.nodup_iff_count_le_one.mp
          exact s.nodup)
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
⊢ ∀ a ∈ Multiset.map (fun p => p) s.val, Prime a

Next tactic:
simpa only [Multiset.map_id', Finset.mem_def] using h
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
⊢ ∀ a ∈ Multiset.map (fun p => p) s.val, a ∣ n

Next tactic:
simpa only [Multiset.map_id', Finset.mem_def] using div
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
⊢ ∀ (a : α), Multiset.countP (Associated a) (Multiset.map (fun p => p) s.val) ≤ 1

Next tactic:
intro a
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
a : α
⊢ Multiset.countP (Associated a) (Multiset.map (fun p => p) s.val) ≤ 1

Next tactic:
simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
a : α
⊢ Multiset.card (Multiset.filter (Eq a) s.val) ≤ 1

Next tactic:
change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
          

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
a : α
⊢ Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1

Next tactic:
apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
          apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
          

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
a : α
⊢ Multiset.count a s.val ≤ 1

Next tactic:
apply Multiset.nodup_iff_count_le_one.mp
theorem Finset.prod_primes_dvd [CancelCommMonoidWithZero α] [Unique αˣ] {s : Finset α} (n : α)
    (h : ∀ a ∈ s, Prime a) (div : ∀ a ∈ s, a ∣ n) : (∏ p in s, p) ∣ n := by
  classical
    exact
      Multiset.prod_primes_dvd n (by simpa only [Multiset.map_id', Finset.mem_def] using h)
        (by simpa only [Multiset.map_id', Finset.mem_def] using div)
        (by
          -- POrting note: was
          -- `simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter, ←
          --    Multiset.count_eq_card_filter_eq, ← Multiset.nodup_iff_count_le_one, s.nodup]`
          intro a
          simp only [Multiset.map_id', associated_eq_eq, Multiset.countP_eq_card_filter]
          change Multiset.card (Multiset.filter (fun b => a = b) s.val) ≤ 1
          apply le_of_eq_of_le (Multiset.count_eq_card_filter_eq _ _).symm
          apply Multiset.nodup_iff_count_le_one.mp
          

Proof state:
case a
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝¹ : CancelCommMonoidWithZero α
inst✝ : Unique αˣ
s : Finset α
n : α
h : ∀ a ∈ s, Prime a
div : ∀ a ∈ s, a ∣ n
a : α
⊢ Multiset.Nodup s.val

Next tactic:
exact s.nodup
theorem prod_mk {p : Multiset α} : (p.map Associates.mk).prod = Associates.mk p.prod :=
  Multiset.induction_on p (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Multiset α
⊢ Multiset.prod (Multiset.map Associates.mk 0) = Associates.mk (Multiset.prod 0)

Next tactic:
simp
theorem prod_mk {p : Multiset α} : (p.map Associates.mk).prod = Associates.mk p.prod :=
  Multiset.induction_on p (by simp) fun a s ih => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Multiset α
a : α
s : Multiset α
ih : Multiset.prod (Multiset.map Associates.mk s) = Associates.mk (Multiset.prod s)
⊢ Multiset.prod (Multiset.map Associates.mk (a ::ₘ s)) = Associates.mk (Multiset.prod (a ::ₘ s))

Next tactic:
simp [ih, Associates.mk_mul_mk]
theorem finset_prod_mk {p : Finset β} {f : β → α} :
    (∏ i in p, Associates.mk (f i)) = Associates.mk (∏ i in p, f i) := by
  -- Porting note: added
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Finset β
f : β → α
⊢ ∏ i in p, Associates.mk (f i) = Associates.mk (∏ i in p, f i)

Next tactic:
have : (fun i => Associates.mk (f i)) = Associates.mk ∘ f :=
    funext <| fun x => Function.comp_apply
theorem finset_prod_mk {p : Finset β} {f : β → α} :
    (∏ i in p, Associates.mk (f i)) = Associates.mk (∏ i in p, f i) := by
  -- Porting note: added
  have : (fun i => Associates.mk (f i)) = Associates.mk ∘ f :=
    funext <| fun x => Function.comp_apply
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Finset β
f : β → α
this : (fun i => Associates.mk (f i)) = Associates.mk ∘ f
⊢ ∏ i in p, Associates.mk (f i) = Associates.mk (∏ i in p, f i)

Next tactic:
rw [Finset.prod_eq_multiset_prod, this, ← Multiset.map_map, prod_mk,
    ← Finset.prod_eq_multiset_prod]
theorem rel_associated_iff_map_eq_map {p q : Multiset α} :
    Multiset.Rel Associated p q ↔ p.map Associates.mk = q.map Associates.mk := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset α
⊢ Multiset.Rel Associated p q ↔ Multiset.map Associates.mk p = Multiset.map Associates.mk q

Next tactic:
rw [← Multiset.rel_eq, Multiset.rel_map]
theorem rel_associated_iff_map_eq_map {p q : Multiset α} :
    Multiset.Rel Associated p q ↔ p.map Associates.mk = q.map Associates.mk := by
  rw [← Multiset.rel_eq, Multiset.rel_map]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset α
⊢ Multiset.Rel Associated p q ↔ Multiset.Rel (fun a b => Associates.mk a = Associates.mk b) p q

Next tactic:
simp only [mk_eq_mk_iff_associated]
theorem prod_eq_one_iff {p : Multiset (Associates α)} :
    p.prod = 1 ↔ ∀ a ∈ p, (a : Associates α) = 1 :=
  Multiset.induction_on p (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Multiset (Associates α)
⊢ Multiset.prod 0 = 1 ↔ ∀ a ∈ 0, a = 1

Next tactic:
simp
theorem prod_eq_one_iff {p : Multiset (Associates α)} :
    p.prod = 1 ↔ ∀ a ∈ p, (a : Associates α) = 1 :=
  Multiset.induction_on p (by simp)
    (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p : Multiset (Associates α)
⊢ ∀ ⦃a : Associates α⦄ {s : Multiset (Associates α)},
    (Multiset.prod s = 1 ↔ ∀ a ∈ s, a = 1) → (Multiset.prod (a ::ₘ s) = 1 ↔ ∀ a_2 ∈ a ::ₘ s, a_2 = 1)

Next tactic:
simp (config := { contextual := true }) [mul_eq_one_iff, or_imp, forall_and]
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
⊢ Multiset.prod p ≤ Multiset.prod q

Next tactic:
haveI := Classical.decEq (Associates α)
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this : DecidableEq (Associates α)
⊢ Multiset.prod p ≤ Multiset.prod q

Next tactic:
haveI := Classical.decEq α
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  haveI := Classical.decEq α
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this✝ : DecidableEq (Associates α)
this : DecidableEq α
⊢ Multiset.prod p ≤ Multiset.prod q

Next tactic:
suffices p.prod ≤ (p + (q - p)).prod by rwa [add_tsub_cancel_of_le h] at this
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  haveI := Classical.decEq α
  suffices p.prod ≤ (p + (q - p)).prod by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this✝¹ : DecidableEq (Associates α)
this✝ : DecidableEq α
this : Multiset.prod p ≤ Multiset.prod (p + (q - p))
⊢ Multiset.prod p ≤ Multiset.prod q

Next tactic:
rwa [add_tsub_cancel_of_le h] at this
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  haveI := Classical.decEq α
  suffices p.prod ≤ (p + (q - p)).prod by rwa [add_tsub_cancel_of_le h] at this
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this✝ : DecidableEq (Associates α)
this : DecidableEq α
⊢ Multiset.prod p ≤ Multiset.prod (p + (q - p))

Next tactic:
suffices p.prod * 1 ≤ p.prod * (q - p).prod by simpa
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  haveI := Classical.decEq α
  suffices p.prod ≤ (p + (q - p)).prod by rwa [add_tsub_cancel_of_le h] at this
  suffices p.prod * 1 ≤ p.prod * (q - p).prod by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this✝¹ : DecidableEq (Associates α)
this✝ : DecidableEq α
this : Multiset.prod p * 1 ≤ Multiset.prod p * Multiset.prod (q - p)
⊢ Multiset.prod p ≤ Multiset.prod (p + (q - p))

Next tactic:
simpa
theorem prod_le_prod {p q : Multiset (Associates α)} (h : p ≤ q) : p.prod ≤ q.prod := by
  haveI := Classical.decEq (Associates α)
  haveI := Classical.decEq α
  suffices p.prod ≤ (p + (q - p)).prod by rwa [add_tsub_cancel_of_le h] at this
  suffices p.prod * 1 ≤ p.prod * (q - p).prod by simpa
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoid α
p q : Multiset (Associates α)
h : p ≤ q
this✝ : DecidableEq (Associates α)
this : DecidableEq α
⊢ Multiset.prod p * 1 ≤ Multiset.prod p * Multiset.prod (q - p)

Next tactic:
exact mul_mono (le_refl p.prod) one_le
theorem exists_mem_multiset_le_of_prime {s : Multiset (Associates α)} {p : Associates α}
    (hp : Prime p) : p ≤ s.prod → ∃ a ∈ s, p ≤ a :=
  Multiset.induction_on s (fun ⟨d, Eq⟩ => (hp.ne_one (mul_eq_one_iff.1 Eq.symm).1).elim)
    fun a s ih h =>
    have : p ≤ a * s.prod := by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
s✝ : Multiset (Associates α)
p : Associates α
hp : Prime p
a : Associates α
s : Multiset (Associates α)
ih : p ≤ Multiset.prod s → ∃ a ∈ s, p ≤ a
h : p ≤ Multiset.prod (a ::ₘ s)
⊢ p ≤ a * Multiset.prod s

Next tactic:
simpa using h
/-- If a stochastic process has bounded upcrossing from below `a` to above `b`,
then it does not frequently visit both below `a` and above `b`. -/
theorem not_frequently_of_upcrossings_lt_top (hab : a < b) (hω : upcrossings a b f ω ≠ ∞) :
    ¬((∃ᶠ n in atTop, f n ω < a) ∧ ∃ᶠ n in atTop, b < f n ω) := by
  

Proof state:
Ω : Type u_1
ι : Type u_2
m0 : MeasurableSpace Ω
μ : Measure Ω
ℱ : Filtration ℕ m0
a b : ℝ
f : ℕ → Ω → ℝ
ω : Ω
R : ℝ≥0
hab : a < b
hω : upcrossings a b f ω ≠ ⊤
⊢ ¬((∃ᶠ (n : ℕ) in atTop, f n ω < a) ∧ ∃ᶠ (n : ℕ) in atTop, b < f n ω)

Next tactic:
rw [← lt_top_iff_ne_top, upcrossings_lt_top_iff] at hω
/-- If a stochastic process has bounded upcrossing from below `a` to above `b`,
then it does not frequently visit both below `a` and above `b`. -/
theorem not_frequently_of_upcrossings_lt_top (hab : a < b) (hω : upcrossings a b f ω ≠ ∞) :
    ¬((∃ᶠ n in atTop, f n ω < a) ∧ ∃ᶠ n in atTop, b < f n ω) := by
  rw [← lt_top_iff_ne_top, upcrossings_lt_top_iff] at hω
  

Proof state:
Ω : Type u_1
ι : Type u_2
m0 : MeasurableSpace Ω
μ : Measure Ω
ℱ : Filtration ℕ m0
a b : ℝ
f : ℕ → Ω → ℝ
ω : Ω
R : ℝ≥0
hab : a < b
hω : ∃ k, ∀ (N : ℕ), upcrossingsBefore a b f N ω ≤ k
⊢ ¬((∃ᶠ (n : ℕ) in atTop, f n ω < a) ∧ ∃ᶠ (n : ℕ) in atTop, b < f n ω)

Next tactic:
replace hω : ∃ k, ∀ N, upcrossingsBefore a b f N ω < k
/-- If a stochastic process has bounded upcrossing from below `a` to above `b`,
then it does not frequently visit both below `a` and above `b`. -/
theorem not_frequently_of_upcrossings_lt_top (hab : a < b) (hω : upcrossings a b f ω ≠ ∞) :
    ¬((∃ᶠ n in atTop, f n ω < a) ∧ ∃ᶠ n in atTop, b < f n ω) := by
  rw [← lt_top_iff_ne_top, upcrossings_lt_top_iff] at hω
  replace hω : ∃ k, ∀ N, upcrossingsBefore a b f N ω < k
  · 

Proof state:
case hω
Ω : Type u_1
ι : Type u_2
m0 : MeasurableSpace Ω
μ : Measure Ω
ℱ : Filtration ℕ m0
a b : ℝ
f : ℕ → Ω → ℝ
ω : Ω
R : ℝ≥0
hab : a < b
hω : ∃ k, ∀ (N : ℕ), upcrossingsBefore a b f N ω ≤ k
⊢ ∃ k, ∀ (N : ℕ), upcrossingsBefore a b f N ω < k

Next tactic:
obtain ⟨k, hk⟩ := hω