l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
⊢ ∀ (g : (a : α) → a ∈ s → α),
    (∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1) →
      (∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a) →
        ∀ (g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s),
          (∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a) → ∏ x in s, f x = 1

Next tactic:
exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      have : y = g x hx := g_inv y (hmem y hy) ▸ by simp [h]
                      simp [this] at hy, g_mem y (hmem y hy)⟩⟩)
            fun y hy => g_inv y (hmem y hy)
        if hx1 : f x = 1 then
          ih' ▸
            Eq.symm
              (prod_subset hmem fun y hy hy₁ =>
                have : y = x ∨ y = g x hx := by
                  simpa [hy, -not_and, mem_erase, not_and_or, or_comm] using hy₁
                this.elim (fun hy => hy.symm ▸ hx1) fun hy =>
                  h x hx ▸ hy ▸ hx1.symm ▸ (one_mul _).symm)
        else by
          rw [← insert_erase hx, prod_insert (not_mem_erase _ _), ←
            insert_erase (mem_erase.2 ⟨g_ne x hx hx1, g_mem x hx⟩),
            prod_insert (not_mem_erase _ _), ih', mul_one, h x hx]
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝¹ : Finset.Nonempty s
x✝ : α
hx✝ : x✝ ∈ s
hmem : ∀ y ∈ erase (erase s x✝) (g x✝ hx✝), y ∈ s
x : α
hx : x ∈ s
y : α
hy : y ∈ s
h : g x hx = g y hy
⊢ x = y

Next tactic:
rw [← g_inv x hx, ← g_inv y hy]
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝¹ : Finset.Nonempty s
x✝ : α
hx✝ : x✝ ∈ s
hmem : ∀ y ∈ erase (erase s x✝) (g x✝ hx✝), y ∈ s
x : α
hx : x ∈ s
y : α
hy : y ∈ s
h : g x hx = g y hy
⊢ g (g x hx) (_ : g x hx ∈ s) = g (g y hy) (_ : g y hy ∈ s)

Next tactic:
simp [h]
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
y : α
hy : y ∈ erase (erase s x) (g x hx)
h : g y (_ : y ∈ s) = g x hx
⊢ False

Next tactic:
simp [g_inj h] at hy
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
y : α
hy : y ∈ erase (erase s x) (g x hx)
h : g y (_ : y ∈ s) = x
⊢ False

Next tactic:
have : y = g x hx := g_inv y (hmem y hy) ▸ by simp [h]
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      have : y = g x hx := g_inv y (hmem y hy) ▸ by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
y : α
hy : y ∈ erase (erase s x) (g x hx)
h : g y (_ : y ∈ s) = x
⊢ g (g y (_ : y ∈ s)) (_ : g y (_ : y ∈ s) ∈ s) = g x hx

Next tactic:
simp [h]
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      have : y = g x hx := g_inv y (hmem y hy) ▸ by simp [h]
                      

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝¹ : DecidableEq α
this✝ : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h✝ : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
y : α
hy : y ∈ erase (erase s x) (g x hx)
h : g y (_ : y ∈ s) = x
this : y = g x hx
⊢ False

Next tactic:
simp [this] at hy
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      have : y = g x hx := g_inv y (hmem y hy) ▸ by simp [h]
                      simp [this] at hy, g_mem y (hmem y hy)⟩⟩)
            fun y hy => g_inv y (hmem y hy)
        if hx1 : f x = 1 then
          ih' ▸
            Eq.symm
              (prod_subset hmem fun y hy hy₁ =>
                have : y = x ∨ y = g x hx := by
                  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
ih' : ∏ y in erase (erase s x) (g x hx), f y = 1
hx1 : f x = 1
y : α
hy : y ∈ s
hy₁ : y ∉ erase (erase s x) (g x hx)
⊢ y = x ∨ y = g x hx

Next tactic:
simpa [hy, -not_and, mem_erase, not_and_or, or_comm] using hy₁
@[to_additive]
theorem prod_involution {s : Finset α} {f : α → β} :
    ∀ (g : ∀ a ∈ s, α) (_ : ∀ a ha, f a * f (g a ha) = 1) (_ : ∀ a ha, f a ≠ 1 → g a ha ≠ a)
      (g_mem : ∀ a ha, g a ha ∈ s) (_ : ∀ a ha, g (g a ha) (g_mem a ha) = a),
      ∏ x in s, f x = 1 := by
  haveI := Classical.decEq α; haveI := Classical.decEq β
  exact
    Finset.strongInductionOn s fun s ih g h g_ne g_mem g_inv =>
      s.eq_empty_or_nonempty.elim (fun hs => hs.symm ▸ rfl) fun ⟨x, hx⟩ =>
        have hmem : ∀ y ∈ (s.erase x).erase (g x hx), y ∈ s := fun y hy =>
          mem_of_mem_erase (mem_of_mem_erase hy)
        have g_inj : ∀ {x hx y hy}, g x hx = g y hy → x = y := fun {x hx y hy} h => by
          rw [← g_inv x hx, ← g_inv y hy]; simp [h]
        have ih' : (∏ y in erase (erase s x) (g x hx), f y) = (1 : β) :=
          ih ((s.erase x).erase (g x hx))
            ⟨Subset.trans (erase_subset _ _) (erase_subset _ _), fun h =>
              not_mem_erase (g x hx) (s.erase x) (h (g_mem x hx))⟩
            (fun y hy => g y (hmem y hy)) (fun y hy => h y (hmem y hy))
            (fun y hy => g_ne y (hmem y hy))
            (fun y hy =>
              mem_erase.2
                ⟨fun h : g y _ = g x hx => by simp [g_inj h] at hy,
                  mem_erase.2
                    ⟨fun h : g y _ = x => by
                      have : y = g x hx := g_inv y (hmem y hy) ▸ by simp [h]
                      simp [this] at hy, g_mem y (hmem y hy)⟩⟩)
            fun y hy => g_inv y (hmem y hy)
        if hx1 : f x = 1 then
          ih' ▸
            Eq.symm
              (prod_subset hmem fun y hy hy₁ =>
                have : y = x ∨ y = g x hx := by
                  simpa [hy, -not_and, mem_erase, not_and_or, or_comm] using hy₁
                this.elim (fun hy => hy.symm ▸ hx1) fun hy =>
                  h x hx ▸ hy ▸ hx1.symm ▸ (one_mul _).symm)
        else by
          

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝¹ s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝ : CommMonoid β
s✝ : Finset α
f : α → β
this✝ : DecidableEq α
this : DecidableEq β
s : Finset α
ih :
  ∀ t ⊂ s,
    ∀ (g : (a : α) → a ∈ t → α),
      (∀ (a : α) (ha : a ∈ t), f a * f (g a ha) = 1) →
        (∀ (a : α) (ha : a ∈ t), f a ≠ 1 → g a ha ≠ a) →
          ∀ (g_mem : ∀ (a : α) (ha : a ∈ t), g a ha ∈ t),
            (∀ (a : α) (ha : a ∈ t), g (g a ha) (_ : g a ha ∈ t) = a) → ∏ x in t, f x = 1
g : (a : α) → a ∈ s → α
h : ∀ (a : α) (ha : a ∈ s), f a * f (g a ha) = 1
g_ne : ∀ (a : α) (ha : a ∈ s), f a ≠ 1 → g a ha ≠ a
g_mem : ∀ (a : α) (ha : a ∈ s), g a ha ∈ s
g_inv : ∀ (a : α) (ha : a ∈ s), g (g a ha) (_ : g a ha ∈ s) = a
x✝ : Finset.Nonempty s
x : α
hx : x ∈ s
hmem : ∀ y ∈ erase (erase s x) (g x hx), y ∈ s
g_inj : ∀ {x : α} {hx : x ∈ s} {y : α} {hy : y ∈ s}, g x hx = g y hy → x = y
ih' : ∏ y in erase (erase s x) (g x hx), f y = 1
hx1 : ¬f x = 1
⊢ ∏ x in s, f x = 1

Next tactic:
rw [← insert_erase hx, prod_insert (not_mem_erase _ _), ←
            insert_erase (mem_erase.2 ⟨g_ne x hx hx1, g_mem x hx⟩),
            prod_insert (not_mem_erase _ _), ih', mul_one, h x hx]
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
⊢ ∀ (a : α) (ha : a ∈ s),
    (fun a _ha => { fst := g a, snd := a }) a ha ∈ Finset.sigma (image g s) fun b => filter (fun a => g a = b) s

Next tactic:
simp
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
⊢ ∀ a ∈ s, (∃ a_1 ∈ s, g a_1 = g a) ∧ a ∈ s

Next tactic:
tauto
/-- The product of the composition of functions `f` and `g`, is the product over `b ∈ s.image g` of
`f b` to the power of the cardinality of the fibre of `b`. See also `Finset.prod_image`. -/
@[to_additive "The sum of the composition of functions `f` and `g`, is the sum over `b ∈ s.image g`
of `f b` times of the cardinality of the fibre of `b`. See also `Finset.sum_image`."]
theorem prod_comp [DecidableEq γ] (f : γ → β) (g : α → γ) :
    (∏ a in s, f (g a)) = ∏ b in s.image g, f b ^ (s.filter fun a => g a = b).card :=
  calc
    (∏ a in s, f (g a)) =
        ∏ x in (s.image g).sigma fun b : γ => s.filter fun a => g a = b, f (g x.2) :=
      prod_bij (fun a _ha => ⟨g a, a⟩) (by simp; tauto) (fun _ _ => rfl) (by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g✝ : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq γ
f : γ → β
g : α → γ
⊢ ∀ (a₁ a₂ : α) (ha₁ : a₁ ∈ s) (ha₂ : a₂ ∈ s),
    (fun a _ha => { fst := g a, snd := a }) a₁ ha₁ = (fun a _ha => { fst := g a, snd := a }) a₂ ha₂ → a₁ = a₂

Next tactic:
simp