Theorem: Finset.filter_product_card
File: Mathlib/Data/Finset/Prod.lean

tactic: rw [← card_product, ← card_product, ← filter_product, ← filter_product, ← card_union_eq]
state_before: α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ card (filter (fun x => p x.fst = q x.snd) (s ×ˢ t)) =
    card (filter p s) * card (filter q t) + card (filter (fun x => ¬p x) s) * card (filter (fun x => ¬q x) t)

tactic: apply congr_arg
state_before: α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ card (filter (fun x => p x.fst = q x.snd) (s ×ˢ t)) =
    card (filter (fun x => p x.fst ∧ q x.snd) (s ×ˢ t) ∪ filter (fun x => ¬p x.fst ∧ ¬q x.snd) (s ×ˢ t))

tactic: ext ⟨a, b⟩
state_before: case h
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ filter (fun x => p x.fst = q x.snd) (s ×ˢ t) =
    filter (fun x => p x.fst ∧ q x.snd) (s ×ˢ t) ∪ filter (fun x => ¬p x.fst ∧ ¬q x.snd) (s ×ˢ t)

tactic: simp only [filter_union_right, mem_filter, mem_product]
state_before: case h.a.mk
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
⊢ (a, b) ∈ filter (fun x => p x.fst = q x.snd) (s ×ˢ t) ↔
    (a, b) ∈ filter (fun x => p x.fst ∧ q x.snd) (s ×ˢ t) ∪ filter (fun x => ¬p x.fst ∧ ¬q x.snd) (s ×ˢ t)

tactic: constructor <;> intro h <;> use h.1
state_before: case h.a.mk
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
⊢ (a ∈ s ∧ b ∈ t) ∧ p a = q b ↔ (a ∈ s ∧ b ∈ t) ∧ (p a ∧ q b ∨ ¬p a ∧ ¬q b)

tactic: . simp only [h.2, Function.comp_apply, Decidable.em, and_self]
state_before: case h.a.mk.mp
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
h : (a ∈ s ∧ b ∈ t) ∧ p a = q b
⊢ p a ∧ q b ∨ ¬p a ∧ ¬q b

case h.a.mk.mpr
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
h : (a ∈ s ∧ b ∈ t) ∧ (p a ∧ q b ∨ ¬p a ∧ ¬q b)
⊢ p a = q b

tactic: . revert h
  simp only [Function.comp_apply, and_imp]
  rintro _ _ (_|_) <;> simp [*]
state_before: case h.a.mk.mpr
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
h : (a ∈ s ∧ b ∈ t) ∧ (p a ∧ q b ∨ ¬p a ∧ ¬q b)
⊢ p a = q b

tactic: simp only [h.2, Function.comp_apply, Decidable.em, and_self]
state_before: case h.a.mk.mp
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
h : (a ∈ s ∧ b ∈ t) ∧ p a = q b
⊢ p a ∧ q b ∨ ¬p a ∧ ¬q b

tactic: revert h
state_before: case h.a.mk.mpr
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
h : (a ∈ s ∧ b ∈ t) ∧ (p a ∧ q b ∨ ¬p a ∧ ¬q b)
⊢ p a = q b

tactic: simp only [Function.comp_apply, and_imp]
state_before: case h.a.mk.mpr
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
⊢ (a ∈ s ∧ b ∈ t) ∧ (p a ∧ q b ∨ ¬p a ∧ ¬q b) → p a = q b

tactic: rintro _ _ (_|_) <;> simp [*]
state_before: case h.a.mk.mpr
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a✝ : α
b✝ : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
a : α
b : β
⊢ a ∈ s → b ∈ t → p a ∧ q b ∨ ¬p a ∧ ¬q b → p a = q b

tactic: apply Finset.disjoint_filter_filter'
state_before: α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ _root_.Disjoint (filter (fun x => p x.fst ∧ q x.snd) (s ×ˢ t)) (filter (fun x => ¬p x.fst ∧ ¬q x.snd) (s ×ˢ t))

tactic: exact (disjoint_compl_right.inf_left _).inf_right _
state_before: case h
α : Type u_1
β : Type u_2
γ : Type ?u.63122
s✝ s' : Finset α
t✝ t' : Finset β
a : α
b : β
s : Finset α
t : Finset β
p : α → Prop
q : β → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidablePred q
⊢ _root_.Disjoint (fun x => p x.fst ∧ q x.snd) fun x => ¬p x.fst ∧ ¬q x.snd