Theorem: Finset.prod_comm'
File: Mathlib/Algebra/BigOperators/Group/Finset.lean

tactic: classical
  have : ∀ z : γ × α, (z ∈ s.biUnion fun x => (t x).map <| Function.Embedding.sectr x _) ↔
    z.1 ∈ s ∧ z.2 ∈ t z.1 := by
    rintro ⟨x, y⟩
    simp only [mem_biUnion, mem_map, Function.Embedding.sectr_apply, Prod.mk.injEq,
      exists_eq_right, ← and_assoc]
  exact
    (prod_finset_product' _ _ _ this).symm.trans
      ((prod_finset_product_right' _ _ _) fun ⟨x, y⟩ => (this _).trans ((h x y).trans and_comm))
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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
⊢ ∏ x ∈ s, ∏ y ∈ t x, f x y = ∏ y ∈ t', ∏ x ∈ s' y, f x y
state_after: no goals

tactic: have : ∀ z : γ × α, (z ∈ s.biUnion fun x => (t x).map <| Function.Embedding.sectr x _) ↔
  z.1 ∈ s ∧ z.2 ∈ t z.1 := by
  rintro ⟨x, y⟩
  simp only [mem_biUnion, mem_map, Function.Embedding.sectr_apply, Prod.mk.injEq,
    exists_eq_right, ← and_assoc]
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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
⊢ ∏ x ∈ s, ∏ y ∈ t x, f x y = ∏ y ∈ t', ∏ x ∈ s' y, f x y
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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
this : ∀ (z : γ × α), (z ∈ s.biUnion fun x => map (Embedding.sectr x α) (t x)) ↔ z.1 ∈ s ∧ z.2 ∈ t z.1
⊢ ∏ x ∈ s, ∏ y ∈ t x, f x y = ∏ y ∈ t', ∏ x ∈ s' y, f x y

tactic: exact
  (prod_finset_product' _ _ _ this).symm.trans
    ((prod_finset_product_right' _ _ _) fun ⟨x, y⟩ => (this _).trans ((h x y).trans and_comm))
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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
this : ∀ (z : γ × α), (z ∈ s.biUnion fun x => map (Embedding.sectr x α) (t x)) ↔ z.1 ∈ s ∧ z.2 ∈ t z.1
⊢ ∏ x ∈ s, ∏ y ∈ t x, f x y = ∏ y ∈ t', ∏ x ∈ s' y, f x y
state_after: no goals

tactic: rintro ⟨x, y⟩
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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
⊢ ∀ (z : γ × α), (z ∈ s.biUnion fun x => map (Embedding.sectr x α) (t x)) ↔ z.1 ∈ s ∧ z.2 ∈ t z.1
state_after: case mk
ι : 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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
x : γ
y : α
⊢ ((x, y) ∈ s.biUnion fun x => map (Embedding.sectr x α) (t x)) ↔ (x, y).1 ∈ s ∧ (x, y).2 ∈ t (x, y).1

tactic: simp only [mem_biUnion, mem_map, Function.Embedding.sectr_apply, Prod.mk.injEq,
  exists_eq_right, ← and_assoc]
state_before: case mk
ι : 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 γ
t : γ → Finset α
t' : Finset α
s' : α → Finset γ
h : ∀ (x : γ) (y : α), x ∈ s ∧ y ∈ t x ↔ x ∈ s' y ∧ y ∈ t'
f : γ → α → β
x : γ
y : α
⊢ ((x, y) ∈ s.biUnion fun x => map (Embedding.sectr x α) (t x)) ↔ (x, y).1 ∈ s ∧ (x, y).2 ∈ t (x, y).1
state_after: no goals