l3lab/ntp-mathlib huggingface dataset:
@[to_additive (attr := simp)]
theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α → β) (g : ¬p → α → β) :
    ∏ x in s, (if h : p then f h x else g h x) =
      if h : p then ∏ x in s, f h x else ∏ x in s, g h x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
p : Prop
inst✝ : Decidable p
s : Finset α
f : p → α → β
g : ¬p → α → β
⊢ (∏ x in s, if h : p then f h x else g h x) = if h : p then ∏ x in s, f h x else ∏ x in s, g h x

Next tactic:
split_ifs with h
@[to_additive (attr := simp)]
theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α → β) (g : ¬p → α → β) :
    ∏ x in s, (if h : p then f h x else g h x) =
      if h : p then ∏ x in s, f h x else ∏ x in s, g h x := by
  split_ifs with h <;> 

Proof state:
case pos
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
p : Prop
inst✝ : Decidable p
s : Finset α
f : p → α → β
g : ¬p → α → β
h : p
⊢ ∏ x in s, f h x = ∏ x in s, f h x

Next tactic:
rfl
@[to_additive (attr := simp)]
theorem prod_dite_irrel (p : Prop) [Decidable p] (s : Finset α) (f : p → α → β) (g : ¬p → α → β) :
    ∏ x in s, (if h : p then f h x else g h x) =
      if h : p then ∏ x in s, f h x else ∏ x in s, g h x := by
  split_ifs with h <;> 

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
p : Prop
inst✝ : Decidable p
s : Finset α
f : p → α → β
g : ¬p → α → β
h : ¬p
⊢ ∏ x in s, g h x = ∏ x in s, g h x

Next tactic:
rfl
@[to_additive]
lemma mulSupport_prod (s : Finset ι) (f : ι → α → β) :
    mulSupport (fun x ↦ ∏ i in s, f i x) ⊆ ⋃ i ∈ s, mulSupport (f i) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset ι
f : ι → α → β
⊢ (mulSupport fun x => ∏ i in s, f i x) ⊆ ⋃ i ∈ s, mulSupport (f i)

Next tactic:
simp only [mulSupport_subset_iff', Set.mem_iUnion, not_exists, nmem_mulSupport]
@[to_additive]
lemma mulSupport_prod (s : Finset ι) (f : ι → α → β) :
    mulSupport (fun x ↦ ∏ i in s, f i x) ⊆ ⋃ i ∈ s, mulSupport (f i) := by
  simp only [mulSupport_subset_iff', Set.mem_iUnion, not_exists, nmem_mulSupport]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset ι
f : ι → α → β
⊢ ∀ (x : α), (∀ x_1 ∈ s, f x_1 x = 1) → ∏ i in s, f i x = 1

Next tactic:
exact fun x ↦ prod_eq_one
/-- Consider a product of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (· ^ n)`, which maps a second argument of `1` to `1`. Then if `f` is replaced by the
corresponding multiplicative indicator function, the finset may be replaced by a possibly larger
finset without changing the value of the product. -/
@[to_additive "Consider a sum of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (n • ·)`, which maps a second argument of `0` to `0` (or a weighted sum of `f i * h i` or
`f i • h i`, where `f` gives the weights that are multiplied by some other function `h`). Then if
`f` is replaced by the corresponding indicator function, the finset may be replaced by a possibly
larger finset without changing the value of the sum."]
lemma prod_mulIndicator_subset_of_eq_one [One α] (f : ι → α) (g : ι → α → β) {s t : Finset ι}
    (h : s ⊆ t) (hg : ∀ a, g a 1 = 1) :
    ∏ i in t, g i (mulIndicator ↑s f i) = ∏ i in s, g i (f i) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
inst✝ : One α
f : ι → α
g : ι → α → β
s t : Finset ι
h : s ⊆ t
hg : ∀ (a : ι), g a 1 = 1
⊢ ∏ i in t, g i (mulIndicator (↑s) f i) = ∏ i in s, g i (f i)

Next tactic:
calc
    _ = ∏ i in s, g i (mulIndicator ↑s f i) := by rw [prod_subset h fun i _ hn ↦ by simp [hn, hg]]
    -- Porting note: This did not use to need the implicit argument
    _ = _ := prod_congr rfl fun i hi ↦ congr_arg _ $ mulIndicator_of_mem (α := ι) hi f
/-- Consider a product of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (· ^ n)`, which maps a second argument of `1` to `1`. Then if `f` is replaced by the
corresponding multiplicative indicator function, the finset may be replaced by a possibly larger
finset without changing the value of the product. -/
@[to_additive "Consider a sum of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (n • ·)`, which maps a second argument of `0` to `0` (or a weighted sum of `f i * h i` or
`f i • h i`, where `f` gives the weights that are multiplied by some other function `h`). Then if
`f` is replaced by the corresponding indicator function, the finset may be replaced by a possibly
larger finset without changing the value of the sum."]
lemma prod_mulIndicator_subset_of_eq_one [One α] (f : ι → α) (g : ι → α → β) {s t : Finset ι}
    (h : s ⊆ t) (hg : ∀ a, g a 1 = 1) :
    ∏ i in t, g i (mulIndicator ↑s f i) = ∏ i in s, g i (f i) := by
  calc
    _ = ∏ i in s, g i (mulIndicator ↑s f i) := by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
inst✝ : One α
f : ι → α
g : ι → α → β
s t : Finset ι
h : s ⊆ t
hg : ∀ (a : ι), g a 1 = 1
⊢ ∏ i in t, g i (mulIndicator (↑s) f i) = ∏ i in s, g i (mulIndicator (↑s) f i)

Next tactic:
rw [prod_subset h fun i _ hn ↦ by simp [hn, hg]]
/-- Consider a product of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (· ^ n)`, which maps a second argument of `1` to `1`. Then if `f` is replaced by the
corresponding multiplicative indicator function, the finset may be replaced by a possibly larger
finset without changing the value of the product. -/
@[to_additive "Consider a sum of `g i (f i)` over a finset.  Suppose `g` is a function such as
`n ↦ (n • ·)`, which maps a second argument of `0` to `0` (or a weighted sum of `f i * h i` or
`f i • h i`, where `f` gives the weights that are multiplied by some other function `h`). Then if
`f` is replaced by the corresponding indicator function, the finset may be replaced by a possibly
larger finset without changing the value of the sum."]
lemma prod_mulIndicator_subset_of_eq_one [One α] (f : ι → α) (g : ι → α → β) {s t : Finset ι}
    (h : s ⊆ t) (hg : ∀ a, g a 1 = 1) :
    ∏ i in t, g i (mulIndicator ↑s f i) = ∏ i in s, g i (f i) := by
  calc
    _ = ∏ i in s, g i (mulIndicator ↑s f i) := by rw [prod_subset h fun i _ hn ↦ by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
inst✝ : One α
f : ι → α
g : ι → α → β
s t : Finset ι
h : s ⊆ t
hg : ∀ (a : ι), g a 1 = 1
i : ι
x✝ : i ∈ t
hn : i ∉ s
⊢ g i (mulIndicator (↑s) f i) = 1

Next tactic:
simp [hn, hg]
@[to_additive]
lemma prod_mulIndicator_eq_prod_filter (s : Finset ι) (f : ι → κ → β) (t : ι → Set κ) (g : ι → κ)
    [DecidablePred fun i ↦ g i ∈ t i] :
    ∏ i in s, mulIndicator (t i) (f i) (g i) = ∏ i in s.filter fun i ↦ g i ∈ t i, f i (g i) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
s : Finset ι
f : ι → κ → β
t : ι → Set κ
g : ι → κ
inst✝ : DecidablePred fun i => g i ∈ t i
⊢ ∏ i in s, mulIndicator (t i) (f i) (g i) = ∏ i in filter (fun i => g i ∈ t i) s, f i (g i)

Next tactic:
refine (prod_filter_mul_prod_filter_not s (fun i ↦ g i ∈ t i) _).symm.trans $
     Eq.trans (congr_arg₂ (· * ·) ?_ ?_) (mul_one _)
@[to_additive]
lemma prod_mulIndicator_eq_prod_filter (s : Finset ι) (f : ι → κ → β) (t : ι → Set κ) (g : ι → κ)
    [DecidablePred fun i ↦ g i ∈ t i] :
    ∏ i in s, mulIndicator (t i) (f i) (g i) = ∏ i in s.filter fun i ↦ g i ∈ t i, f i (g i) := by
  refine (prod_filter_mul_prod_filter_not s (fun i ↦ g i ∈ t i) _).symm.trans $
     Eq.trans (congr_arg₂ (· * ·) ?_ ?_) (mul_one _)
  · 

Proof state:
case refine_1
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
s : Finset ι
f : ι → κ → β
t : ι → Set κ
g : ι → κ
inst✝ : DecidablePred fun i => g i ∈ t i
⊢ ∏ x in filter (fun i => g i ∈ t i) s, mulIndicator (t x) (f x) (g x) = ∏ i in filter (fun i => g i ∈ t i) s, f i (g i)

Next tactic:
exact prod_congr rfl fun x hx ↦ mulIndicator_of_mem (mem_filter.1 hx).2 _
@[to_additive]
lemma prod_mulIndicator_eq_prod_filter (s : Finset ι) (f : ι → κ → β) (t : ι → Set κ) (g : ι → κ)
    [DecidablePred fun i ↦ g i ∈ t i] :
    ∏ i in s, mulIndicator (t i) (f i) (g i) = ∏ i in s.filter fun i ↦ g i ∈ t i, f i (g i) := by
  refine (prod_filter_mul_prod_filter_not s (fun i ↦ g i ∈ t i) _).symm.trans $
     Eq.trans (congr_arg₂ (· * ·) ?_ ?_) (mul_one _)
  · exact prod_congr rfl fun x hx ↦ mulIndicator_of_mem (mem_filter.1 hx).2 _
  · 

Proof state:
case refine_2
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
κ : Type u_2
s : Finset ι
f : ι → κ → β
t : ι → Set κ
g : ι → κ
inst✝ : DecidablePred fun i => g i ∈ t i
⊢ ∏ x in filter (fun x => g x ∉ t x) s, mulIndicator (t x) (f x) (g x) = 1

Next tactic:
exact prod_eq_one fun x hx ↦ mulIndicator_of_not_mem (mem_filter.1 hx).2 _
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s : Finset ι
t : ι → Set κ
f : κ → β
⊢ PairwiseDisjoint (↑s) t → mulIndicator (⋃ i ∈ s, t i) f = fun a => ∏ i in s, mulIndicator (t i) f a

Next tactic:
classical
  refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_
  rw [prod_insert hi, set_biUnion_insert, mulIndicator_union_of_not_mem_inter,
    ih (hs.subset $ subset_insert _ _)]
  simp only [not_exists, exists_prop, mem_iUnion, mem_inter_iff, not_and]
  exact fun hji i' hi' hji' ↦ (ne_of_mem_of_not_mem hi' hi).symm $
    hs.elim_set (mem_insert_self _ _) (mem_insert_of_mem hi') _ hji hji'
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  classical
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s : Finset ι
t : ι → Set κ
f : κ → β
⊢ PairwiseDisjoint (↑s) t → mulIndicator (⋃ i ∈ s, t i) f = fun a => ∏ i in s, mulIndicator (t i) f a

Next tactic:
refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  classical
  refine Finset.induction_on s (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s : Finset ι
t : ι → Set κ
f : κ → β
⊢ PairwiseDisjoint (↑∅) t → mulIndicator (⋃ i ∈ ∅, t i) f = fun a => ∏ i in ∅, mulIndicator (t i) f a

Next tactic:
simp
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  classical
  refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s✝ : Finset ι
t : ι → Set κ
f : κ → β
i : ι
s : Finset ι
hi : i ∉ s
ih : PairwiseDisjoint (↑s) t → mulIndicator (⋃ i ∈ s, t i) f = fun a => ∏ i in s, mulIndicator (t i) f a
hs : PairwiseDisjoint (↑(insert i s)) t
j : κ
⊢ mulIndicator (⋃ i_1 ∈ insert i s, t i_1) f j = ∏ i in insert i s, mulIndicator (t i) f j

Next tactic:
rw [prod_insert hi, set_biUnion_insert, mulIndicator_union_of_not_mem_inter,
    ih (hs.subset $ subset_insert _ _)]
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  classical
  refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_
  rw [prod_insert hi, set_biUnion_insert, mulIndicator_union_of_not_mem_inter,
    ih (hs.subset $ subset_insert _ _)]
  

Proof state:
case h
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s✝ : Finset ι
t : ι → Set κ
f : κ → β
i : ι
s : Finset ι
hi : i ∉ s
ih : PairwiseDisjoint (↑s) t → mulIndicator (⋃ i ∈ s, t i) f = fun a => ∏ i in s, mulIndicator (t i) f a
hs : PairwiseDisjoint (↑(insert i s)) t
j : κ
⊢ j ∉ t i ∩ ⋃ x ∈ s, t x

Next tactic:
simp only [not_exists, exists_prop, mem_iUnion, mem_inter_iff, not_and]
@[to_additive]
lemma mulIndicator_biUnion (s : Finset ι) (t : ι → Set κ) {f : κ → β} :
    ((s : Set ι).PairwiseDisjoint t) →
      mulIndicator (⋃ i ∈ s, t i) f = fun a ↦ ∏ i in s, mulIndicator (t i) f a := by
  classical
  refine Finset.induction_on s (by simp) fun i s hi ih hs ↦ funext fun j ↦ ?_
  rw [prod_insert hi, set_biUnion_insert, mulIndicator_union_of_not_mem_inter,
    ih (hs.subset $ subset_insert _ _)]
  simp only [not_exists, exists_prop, mem_iUnion, mem_inter_iff, not_and]
  

Proof state:
case h
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s✝ : Finset ι
t : ι → Set κ
f : κ → β
i : ι
s : Finset ι
hi : i ∉ s
ih : PairwiseDisjoint (↑s) t → mulIndicator (⋃ i ∈ s, t i) f = fun a => ∏ i in s, mulIndicator (t i) f a
hs : PairwiseDisjoint (↑(insert i s)) t
j : κ
⊢ j ∈ t i → ∀ x ∈ s, j ∉ t x

Next tactic:
exact fun hji i' hi' hji' ↦ (ne_of_mem_of_not_mem hi' hi).symm $
    hs.elim_set (mem_insert_self _ _) (mem_insert_of_mem hi') _ hji hji'
@[to_additive]
lemma mulIndicator_biUnion_apply (s : Finset ι) (t : ι → Set κ) {f : κ → β}
    (h : (s : Set ι).PairwiseDisjoint t) (x : κ) :
    mulIndicator (⋃ i ∈ s, t i) f x = ∏ i in s, mulIndicator (t i) f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
κ✝ : Type u_2
κ : Type u_3
s : Finset ι
t : ι → Set κ
f : κ → β
h : PairwiseDisjoint (↑s) t
x : κ
⊢ mulIndicator (⋃ i ∈ s, t i) f x = ∏ i in s, mulIndicator (t i) f x

Next tactic:
rw [mulIndicator_biUnion s t h]
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
⊢ ∏ x in s, f x = ∏ x in t, g x

Next tactic:
classical
  calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one]
    _ = ∏ x in t.filter fun x => g x ≠ 1, g x :=
      prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by simpa using (mem_filter.mp ha).2)
        ?_ ?_ ?_ ?_
    _ = ∏ x in t, g x := prod_filter_ne_one _
  · intros a ha
    refine' (mem_filter.mp ha).elim _
    intros h₁ h₂
    refine (mem_filter.mpr ⟨hi a h₁ _, ?_⟩)
    specialize h a h₁ fun H ↦ by rw [H] at h₂; simp at h₂
    rwa [← h]
  · refine' (fun a ha => (mem_filter.mp ha).elim fun h₁ h₂ ↦ _)
    exact h a h₁ fun H ↦ by rw [H] at h₂; simp at h₂
  · intros a₁ a₂ ha₁ ha₂
    refine' (mem_filter.mp ha₁).elim fun _ha₁₁ _ha₁₂ ↦ _
    refine' (mem_filter.mp ha₂).elim fun _ha₂₁ _ha₂₂ ↦ _
    apply i_inj
  · intros b hb
    refine' (mem_filter.mp hb).elim fun h₁ h₂ ↦ _
    obtain ⟨a, ha₁, ha₂, eq⟩ := i_surj b h₁ fun H ↦ by rw [H] at h₂; simp at h₂
    exact ⟨a, mem_filter.mpr ⟨ha₁, ha₂⟩, eq⟩
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  classical
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
⊢ ∏ x in s, f x = ∏ x in t, g x

Next tactic:
calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one]
    _ = ∏ x in t.filter fun x => g x ≠ 1, g x :=
      prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by simpa using (mem_filter.mp ha).2)
        ?_ ?_ ?_ ?_
    _ = ∏ x in t, g x := prod_filter_ne_one _
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  classical
  calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
⊢ ∏ x in s, f x = ∏ x in filter (fun x => f x ≠ 1) s, f x

Next tactic:
rw [prod_filter_ne_one]
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  classical
  calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one]
    _ = ∏ x in t.filter fun x => g x ≠ 1, g x :=
      prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
a : α
ha : a ∈ filter (fun x => f x ≠ 1) s
⊢ f a ≠ 1

Next tactic:
simpa using (mem_filter.mp ha).2
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  classical
  calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one]
    _ = ∏ x in t.filter fun x => g x ≠ 1, g x :=
      prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by simpa using (mem_filter.mp ha).2)
        ?_ ?_ ?_ ?_
    _ = ∏ x in t, g x := prod_filter_ne_one _
  · 

Proof state:
case calc_1
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
⊢ ∀ (a : α) (ha : a ∈ filter (fun x => f x ≠ 1) s),
    (fun a ha => i a (_ : a ∈ s) (_ : f a ≠ 1)) a ha ∈ filter (fun x => g x ≠ 1) t

Next tactic:
intros a ha
@[to_additive]
theorem prod_bij_ne_one {s : Finset α} {t : Finset γ} {f : α → β} {g : γ → β}
    (i : ∀ a ∈ s, f a ≠ 1 → γ) (hi : ∀ a h₁ h₂, i a h₁ h₂ ∈ t)
    (i_inj : ∀ a₁ a₂ h₁₁ h₁₂ h₂₁ h₂₂, i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂)
    (i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a h₁ h₂, b = i a h₁ h₂) (h : ∀ a h₁ h₂, f a = g (i a h₁ h₂)) :
    ∏ x in s, f x = ∏ x in t, g x := by
  classical
  calc
    ∏ x in s, f x = ∏ x in s.filter fun x => f x ≠ 1, f x := by rw [prod_filter_ne_one]
    _ = ∏ x in t.filter fun x => g x ≠ 1, g x :=
      prod_bij (fun a ha => i a (mem_filter.mp ha).1 $ by simpa using (mem_filter.mp ha).2)
        ?_ ?_ ?_ ?_
    _ = ∏ x in t, g x := prod_filter_ne_one _
  · intros a ha
    

Proof state:
case calc_1
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a✝ : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s : Finset α
t : Finset γ
f : α → β
g : γ → β
i : (a : α) → a ∈ s → f a ≠ 1 → γ
hi : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), i a h₁ h₂ ∈ t
i_inj :
  ∀ (a₁ a₂ : α) (h₁₁ : a₁ ∈ s) (h₁₂ : f a₁ ≠ 1) (h₂₁ : a₂ ∈ s) (h₂₂ : f a₂ ≠ 1), i a₁ h₁₁ h₁₂ = i a₂ h₂₁ h₂₂ → a₁ = a₂
i_surj : ∀ b ∈ t, g b ≠ 1 → ∃ a, ∃ (h₁ : a ∈ s) (h₂ : f a ≠ 1), b = i a h₁ h₂
h : ∀ (a : α) (h₁ : a ∈ s) (h₂ : f a ≠ 1), f a = g (i a h₁ h₂)
a : α
ha : a ∈ filter (fun x => f x ≠ 1) s
⊢ (fun a ha => i a (_ : a ∈ s) (_ : f a ≠ 1)) a ha ∈ filter (fun x => g x ≠ 1) t

Next tactic:
refine' (mem_filter.mp ha).elim _