Theorem: Finset.prod_involution
File: Mathlib/Algebra/BigOperators/Group/Finset.lean

Proof steps:
state_before: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
f : α → β
⊢ ∀ (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) ⋯ = a) → ∏ x ∈ s, f x = 1
state_after: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
f : α → β
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) ⋯ = a) → ∏ x ∈ s, f x = 1
tactic: haveI := Classical.decEq α
state_before: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
f : α → β
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) ⋯ = a) → ∏ x ∈ s, f x = 1
state_after: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
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) ⋯ = a) → ∏ x ∈ s, f x = 1
tactic: haveI := Classical.decEq β
state_before: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
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) ⋯ = a) → ∏ x ∈ s, f x = 1
state_after: no goals
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 ∈ 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]