l3lab/ntp-mathlib huggingface dataset:
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · 

Proof state:
case h.mpr.inl.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.1 ∈ s
h1 : x.2 ∈ t
⊢ ¬x.1 = x.2

Next tactic:
rintro h3
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · rintro h3
      

Proof state:
case h.mpr.inl.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.1 ∈ s
h1 : x.2 ∈ t
h3 : x.1 = x.2
⊢ False

Next tactic:
rw [h3] at h0
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · rintro h3
      rw [h3] at h0
      

Proof state:
case h.mpr.inl.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.2 ∈ s
h1 : x.2 ∈ t
h3 : x.1 = x.2
⊢ False

Next tactic:
exact (Set.disjoint_left.mp h h0 h1)
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · rintro h3
      rw [h3] at h0
      exact (Set.disjoint_left.mp h h0 h1)
    · 

Proof state:
case h.mpr.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.1 ∈ t
h1 : x.2 ∈ s
⊢ ¬x.1 = x.2

Next tactic:
rintro h3
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · rintro h3
      rw [h3] at h0
      exact (Set.disjoint_left.mp h h0 h1)
    · rintro h3
      

Proof state:
case h.mpr.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.1 ∈ t
h1 : x.2 ∈ s
h3 : x.1 = x.2
⊢ False

Next tactic:
rw [h3] at h0
theorem offDiag_union (h : Disjoint s t) :
    (s ∪ t).offDiag = s.offDiag ∪ t.offDiag ∪ s ×ˢ t ∪ t ×ˢ s := by
  ext x
  simp only [mem_offDiag, mem_union, ne_eq, mem_prod]
  constructor
  · rintro ⟨h0|h0, h1|h1, h2⟩ <;> simp [h0, h1, h2]
  · rintro (((⟨h0, h1, h2⟩|⟨h0, h1, h2⟩)|⟨h0, h1⟩)|⟨h0, h1⟩) <;> simp [*]
    · rintro h3
      rw [h3] at h0
      exact (Set.disjoint_left.mp h h0 h1)
    · rintro h3
      rw [h3] at h0
      

Proof state:
case h.mpr.inr.intro
α : Type u_1
s t : Set α
x✝ : α × α
a : α
h : Disjoint s t
x : α × α
h0 : x.2 ∈ t
h1 : x.2 ∈ s
h3 : x.1 = x.2
⊢ False

Next tactic:
exact (Set.disjoint_right.mp h h0 h1).elim
theorem offDiag_insert (ha : a ∉ s) : (insert a s).offDiag = s.offDiag ∪ {a} ×ˢ s ∪ s ×ˢ {a} := by
  

Proof state:
α : Type u_1
s t : Set α
x : α × α
a : α
ha : a ∉ s
⊢ offDiag (insert a s) = offDiag s ∪ {a} ×ˢ s ∪ s ×ˢ {a}

Next tactic:
rw [insert_eq, union_comm, offDiag_union, offDiag_singleton, union_empty, union_right_comm]
theorem offDiag_insert (ha : a ∉ s) : (insert a s).offDiag = s.offDiag ∪ {a} ×ˢ s ∪ s ×ˢ {a} := by
  rw [insert_eq, union_comm, offDiag_union, offDiag_singleton, union_empty, union_right_comm]
  

Proof state:
α : Type u_1
s t : Set α
x : α × α
a : α
ha : a ∉ s
⊢ Disjoint s {a}

Next tactic:
rw [disjoint_left]
theorem offDiag_insert (ha : a ∉ s) : (insert a s).offDiag = s.offDiag ∪ {a} ×ˢ s ∪ s ×ˢ {a} := by
  rw [insert_eq, union_comm, offDiag_union, offDiag_singleton, union_empty, union_right_comm]
  rw [disjoint_left]
  

Proof state:
α : Type u_1
s t : Set α
x : α × α
a : α
ha : a ∉ s
⊢ ∀ ⦃a_1 : α⦄, a_1 ∈ s → a_1 ∉ {a}

Next tactic:
rintro b hb (rfl : b = a)
theorem offDiag_insert (ha : a ∉ s) : (insert a s).offDiag = s.offDiag ∪ {a} ×ˢ s ∪ s ×ˢ {a} := by
  rw [insert_eq, union_comm, offDiag_union, offDiag_singleton, union_empty, union_right_comm]
  rw [disjoint_left]
  rintro b hb (rfl : b = a)
  

Proof state:
α : Type u_1
s t : Set α
x : α × α
b : α
hb : b ∈ s
ha : b ∉ s
⊢ False

Next tactic:
exact ha hb
theorem mem_univ_pi {f : ∀ i, α i} : f ∈ pi univ t ↔ ∀ i, f i ∈ t i := by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f : (i : ι) → α i
⊢ f ∈ pi univ t ↔ ∀ (i : ι), f i ∈ t i

Next tactic:
simp
@[simp]
theorem empty_pi (s : ∀ i, Set (α i)) : pi ∅ s = univ := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : (i : ι) → Set (α i)
⊢ pi ∅ s = univ

Next tactic:
ext
@[simp]
theorem empty_pi (s : ∀ i, Set (α i)) : pi ∅ s = univ := by
  ext
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ x✝ ∈ pi ∅ s ↔ x✝ ∈ univ

Next tactic:
simp [pi]
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
⊢ (pi univ fun i => if i ∈ s then t i else univ) = pi s t

Next tactic:
ext
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; 

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ (x✝ ∈ pi univ fun i => if i ∈ s then t i else univ) ↔ x✝ ∈ pi s t

Next tactic:
simp_rw [Set.mem_pi]
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; simp_rw [Set.mem_pi]; 

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ (∀ i ∈ univ, x✝ i ∈ if i ∈ s then t i else univ) ↔ ∀ i ∈ s, x✝ i ∈ t i

Next tactic:
apply forall_congr'
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; simp_rw [Set.mem_pi]; apply forall_congr'; 

Proof state:
case h.h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ ∀ (a : ι), (a ∈ univ → x✝ a ∈ if a ∈ s then t a else univ) ↔ a ∈ s → x✝ a ∈ t a

Next tactic:
intro i
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; simp_rw [Set.mem_pi]; apply forall_congr'; intro i; 

Proof state:
case h.h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
i : ι
⊢ (i ∈ univ → x✝ i ∈ if i ∈ s then t i else univ) ↔ i ∈ s → x✝ i ∈ t i

Next tactic:
split_ifs with h
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; simp_rw [Set.mem_pi]; apply forall_congr'; intro i; split_ifs with h <;> 

Proof state:
case pos
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
i : ι
h : i ∈ s
⊢ i ∈ univ → x✝ i ∈ t i ↔ i ∈ s → x✝ i ∈ t i

Next tactic:
simp [h]
@[simp]
theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) :
    (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by
  ext; simp_rw [Set.mem_pi]; apply forall_congr'; intro i; split_ifs with h <;> 

Proof state:
case neg
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ : ι
s : Set ι
inst✝ : DecidablePred fun x => x ∈ s
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
i : ι
h : i ∉ s
⊢ i ∈ univ → x✝ i ∈ univ ↔ i ∈ s → x✝ i ∈ t i

Next tactic:
simp [h]
theorem pi_inter_distrib : (s.pi fun i => t i ∩ t₁ i) = s.pi t ∩ s.pi t₁ :=
  ext fun x => by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
x : (i : ι) → α i
⊢ (x ∈ pi s fun i => t i ∩ t₁ i) ↔ x ∈ pi s t ∩ pi s t₁

Next tactic:
simp only [forall_and, mem_pi, mem_inter_iff]
theorem pi_eq_empty (hs : i ∈ s) (ht : t i = ∅) : s.pi t = ∅ := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
hs : i ∈ s
ht : t i = ∅
⊢ pi s t = ∅

Next tactic:
ext f
theorem pi_eq_empty (hs : i ∈ s) (ht : t i = ∅) : s.pi t = ∅ := by
  ext f
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
hs : i ∈ s
ht : t i = ∅
f : (i : ι) → α i
⊢ f ∈ pi s t ↔ f ∈ ∅

Next tactic:
simp only [mem_empty_iff_false, not_forall, iff_false_iff, mem_pi, not_imp]
theorem pi_eq_empty (hs : i ∈ s) (ht : t i = ∅) : s.pi t = ∅ := by
  ext f
  simp only [mem_empty_iff_false, not_forall, iff_false_iff, mem_pi, not_imp]
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
hs : i ∈ s
ht : t i = ∅
f : (i : ι) → α i
⊢ ∃ x ∈ s, f x ∉ t x

Next tactic:
exact ⟨i, hs, by simp [ht]⟩
theorem pi_eq_empty (hs : i ∈ s) (ht : t i = ∅) : s.pi t = ∅ := by
  ext f
  simp only [mem_empty_iff_false, not_forall, iff_false_iff, mem_pi, not_imp]
  exact ⟨i, hs, by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
hs : i ∈ s
ht : t i = ∅
f : (i : ι) → α i
⊢ f i ∉ t i

Next tactic:
simp [ht]
theorem pi_nonempty_iff : (s.pi t).Nonempty ↔ ∀ i, ∃ x, i ∈ s → x ∈ t i := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ Set.Nonempty (pi s t) ↔ ∀ (i : ι), ∃ x, i ∈ s → x ∈ t i

Next tactic:
simp [Classical.skolem, Set.Nonempty]
theorem univ_pi_nonempty_iff : (pi univ t).Nonempty ↔ ∀ i, (t i).Nonempty := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ Set.Nonempty (pi univ t) ↔ ∀ (i : ι), Set.Nonempty (t i)

Next tactic:
simp [Classical.skolem, Set.Nonempty]
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ pi s t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ (¬∀ (i : ι), ∃ x, i ∈ s → x ∈ t i) ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
push_neg
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
  push_neg
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ (∃ i, ∀ (x : α i), i ∈ s ∧ x ∉ t i) ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
refine' exists_congr fun i => _
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
  push_neg
  refine' exists_congr fun i => _
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
⊢ (∀ (x : α i), i ∈ s ∧ x ∉ t i) ↔ IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
cases isEmpty_or_nonempty (α i)
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
  push_neg
  refine' exists_congr fun i => _
  cases isEmpty_or_nonempty (α i) <;> 

Proof state:
case inl
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
h✝ : IsEmpty (α i)
⊢ (∀ (x : α i), i ∈ s ∧ x ∉ t i) ↔ IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
simp [*, forall_and, eq_empty_iff_forall_not_mem]
theorem pi_eq_empty_iff : s.pi t = ∅ ↔ ∃ i, IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅ := by
  rw [← not_nonempty_iff_eq_empty, pi_nonempty_iff]
  push_neg
  refine' exists_congr fun i => _
  cases isEmpty_or_nonempty (α i) <;> 

Proof state:
case inr
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
h✝ : Nonempty (α i)
⊢ (∀ (x : α i), i ∈ s ∧ x ∉ t i) ↔ IsEmpty (α i) ∨ i ∈ s ∧ t i = ∅

Next tactic:
simp [*, forall_and, eq_empty_iff_forall_not_mem]
@[simp]
theorem univ_pi_eq_empty_iff : pi univ t = ∅ ↔ ∃ i, t i = ∅ := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ pi univ t = ∅ ↔ ∃ i, t i = ∅

Next tactic:
simp [← not_nonempty_iff_eq_empty, univ_pi_nonempty_iff]
@[simp]
theorem disjoint_univ_pi : Disjoint (pi univ t₁) (pi univ t₂) ↔ ∃ i, Disjoint (t₁ i) (t₂ i) := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
⊢ Disjoint (pi univ t₁) (pi univ t₂) ↔ ∃ i, Disjoint (t₁ i) (t₂ i)

Next tactic:
simp only [disjoint_iff_inter_eq_empty, ← pi_inter_distrib, univ_pi_eq_empty_iff]
theorem uniqueElim_preimage [Unique ι] (t : ∀ i, Set (α i)) :
    uniqueElim ⁻¹' pi univ t = t (default : ι) := by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
inst✝ : Unique ι
t : (i : ι) → Set (α i)
⊢ uniqueElim ⁻¹' pi univ t = t default

Next tactic:
ext
theorem uniqueElim_preimage [Unique ι] (t : ∀ i, Set (α i)) :
    uniqueElim ⁻¹' pi univ t = t (default : ι) := by ext; 

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i : ι
inst✝ : Unique ι
t : (i : ι) → Set (α i)
x✝ : α default
⊢ x✝ ∈ uniqueElim ⁻¹' pi univ t ↔ x✝ ∈ t default

Next tactic:
simp [Unique.forall_iff]
theorem pi_eq_empty_iff' : s.pi t = ∅ ↔ ∃ i ∈ s, t i = ∅ := by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
inst✝ : ∀ (i : ι), Nonempty (α i)
⊢ pi s t = ∅ ↔ ∃ i ∈ s, t i = ∅

Next tactic:
simp [pi_eq_empty_iff]
@[simp]
theorem disjoint_pi : Disjoint (s.pi t₁) (s.pi t₂) ↔ ∃ i ∈ s, Disjoint (t₁ i) (t₂ i) := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
inst✝ : ∀ (i : ι), Nonempty (α i)
⊢ Disjoint (pi s t₁) (pi s t₂) ↔ ∃ i ∈ s, Disjoint (t₁ i) (t₂ i)

Next tactic:
simp only [disjoint_iff_inter_eq_empty, ← pi_inter_distrib, pi_eq_empty_iff']
theorem range_dcomp (f : ∀ i, α i → β i) :
    (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f : (i : ι) → α i → β i
⊢ (range fun g i => f i (g i)) = pi univ fun i => range (f i)

Next tactic:
refine Subset.antisymm ?_ fun x hx => ?_
theorem range_dcomp (f : ∀ i, α i → β i) :
    (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by
  refine Subset.antisymm ?_ fun x hx => ?_
  · 

Proof state:
case refine_1
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f : (i : ι) → α i → β i
⊢ (range fun g i => f i (g i)) ⊆ pi univ fun i => range (f i)

Next tactic:
rintro _ ⟨x, rfl⟩ i -
theorem range_dcomp (f : ∀ i, α i → β i) :
    (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by
  refine Subset.antisymm ?_ fun x hx => ?_
  · rintro _ ⟨x, rfl⟩ i -
    

Proof state:
case refine_1.intro
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i✝ : ι
f : (i : ι) → α i → β i
x : (i : ι) → α i
i : ι
⊢ (fun g i => f i (g i)) x i ∈ (fun i => range (f i)) i

Next tactic:
exact ⟨x i, rfl⟩
theorem range_dcomp (f : ∀ i, α i → β i) :
    (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by
  refine Subset.antisymm ?_ fun x hx => ?_
  · rintro _ ⟨x, rfl⟩ i -
    exact ⟨x i, rfl⟩
  · 

Proof state:
case refine_2
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f : (i : ι) → α i → β i
x : (i : ι) → β i
hx : x ∈ pi univ fun i => range (f i)
⊢ x ∈ range fun g i => f i (g i)

Next tactic:
choose y hy using hx
theorem range_dcomp (f : ∀ i, α i → β i) :
    (range fun g : ∀ i, α i => fun i => f i (g i)) = pi univ fun i => range (f i) := by
  refine Subset.antisymm ?_ fun x hx => ?_
  · rintro _ ⟨x, rfl⟩ i -
    exact ⟨x i, rfl⟩
  · choose y hy using hx
    

Proof state:
case refine_2
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f : (i : ι) → α i → β i
x : (i : ι) → β i
y : (i : ι) → i ∈ univ → α i
hy : ∀ (i : ι) (a : i ∈ univ), f i (y i a) = x i
⊢ x ∈ range fun g i => f i (g i)

Next tactic:
exact ⟨fun i => y i trivial, funext fun i => hy i trivial⟩
@[simp]
theorem insert_pi (i : ι) (s : Set ι) (t : ∀ i, Set (α i)) :
    pi (insert i s) t = eval i ⁻¹' t i ∩ pi s t := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
s : Set ι
t : (i : ι) → Set (α i)
⊢ pi (insert i s) t = eval i ⁻¹' t i ∩ pi s t

Next tactic:
ext
@[simp]
theorem insert_pi (i : ι) (s : Set ι) (t : ∀ i, Set (α i)) :
    pi (insert i s) t = eval i ⁻¹' t i ∩ pi s t := by
  ext
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
s : Set ι
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ x✝ ∈ pi (insert i s) t ↔ x✝ ∈ eval i ⁻¹' t i ∩ pi s t

Next tactic:
simp [pi, or_imp, forall_and]
@[simp]
theorem singleton_pi (i : ι) (t : ∀ i, Set (α i)) : pi {i} t = eval i ⁻¹' t i := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
t : (i : ι) → Set (α i)
⊢ pi {i} t = eval i ⁻¹' t i

Next tactic:
ext
@[simp]
theorem singleton_pi (i : ι) (t : ∀ i, Set (α i)) : pi {i} t = eval i ⁻¹' t i := by
  ext
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t✝ t₁ t₂ : (i : ι) → Set (α i)
i✝ i : ι
t : (i : ι) → Set (α i)
x✝ : (i : ι) → α i
⊢ x✝ ∈ pi {i} t ↔ x✝ ∈ eval i ⁻¹' t i

Next tactic:
simp [pi]
theorem univ_pi_singleton (f : ∀ i, α i) : (pi univ fun i => {f i}) = ({f} : Set (∀ i, α i)) :=
  ext fun g => by 

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s s₁ s₂ : Set ι
t t₁ t₂ : (i : ι) → Set (α i)
i : ι
f g : (i : ι) → α i
⊢ (g ∈ pi univ fun i => {f i}) ↔ g ∈ {f}

Next tactic:
simp [funext_iff]
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  

Proof state:
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i : ι
p : ι → Prop
h : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
⊢ (pi s fun i => if p i then t₁ i else t₂ i) = pi {i | i ∈ s ∧ p i} t₁ ∩ pi {i | i ∈ s ∧ ¬p i} t₂

Next tactic:
ext f
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  

Proof state:
case h
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i : ι
p : ι → Prop
h : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
⊢ (f ∈ pi s fun i => if p i then t₁ i else t₂ i) ↔ f ∈ pi {i | i ∈ s ∧ p i} t₁ ∩ pi {i | i ∈ s ∧ ¬p i} t₂

Next tactic:
refine' ⟨fun h => _, _⟩
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  refine' ⟨fun h => _, _⟩
  · 

Proof state:
case h.refine'_1
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i : ι
p : ι → Prop
h✝ : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
h : f ∈ pi s fun i => if p i then t₁ i else t₂ i
⊢ f ∈ pi {i | i ∈ s ∧ p i} t₁ ∩ pi {i | i ∈ s ∧ ¬p i} t₂

Next tactic:
constructor
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  refine' ⟨fun h => _, _⟩
  · constructor <;>
      · 

Proof state:
case h.refine'_1.left
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i : ι
p : ι → Prop
h✝ : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
h : f ∈ pi s fun i => if p i then t₁ i else t₂ i
⊢ f ∈ pi {i | i ∈ s ∧ p i} t₁

Next tactic:
rintro i ⟨his, hpi⟩
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  refine' ⟨fun h => _, _⟩
  · constructor <;>
      · rintro i ⟨his, hpi⟩
        

Proof state:
case h.refine'_1.left.intro
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i✝ : ι
p : ι → Prop
h✝ : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
h : f ∈ pi s fun i => if p i then t₁ i else t₂ i
i : ι
his : i ∈ s
hpi : p i
⊢ f i ∈ t₁ i

Next tactic:
simpa [*] using h i
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  refine' ⟨fun h => _, _⟩
  · constructor <;>
      · 

Proof state:
case h.refine'_1.right
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i : ι
p : ι → Prop
h✝ : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
h : f ∈ pi s fun i => if p i then t₁ i else t₂ i
⊢ f ∈ pi {i | i ∈ s ∧ ¬p i} t₂

Next tactic:
rintro i ⟨his, hpi⟩
theorem pi_if {p : ι → Prop} [h : DecidablePred p] (s : Set ι) (t₁ t₂ : ∀ i, Set (α i)) :
    (pi s fun i => if p i then t₁ i else t₂ i) =
      pi ({ i ∈ s | p i }) t₁ ∩ pi ({ i ∈ s | ¬p i }) t₂ := by
  ext f
  refine' ⟨fun h => _, _⟩
  · constructor <;>
      · rintro i ⟨his, hpi⟩
        

Proof state:
case h.refine'_1.right.intro
ι : Type u_1
α : ι → Type u_2
β : ι → Type u_3
s✝ s₁ s₂ : Set ι
t t₁✝ t₂✝ : (i : ι) → Set (α i)
i✝ : ι
p : ι → Prop
h✝ : DecidablePred p
s : Set ι
t₁ t₂ : (i : ι) → Set (α i)
f : (i : ι) → α i
h : f ∈ pi s fun i => if p i then t₁ i else t₂ i
i : ι
his : i ∈ s
hpi : ¬p i
⊢ f i ∈ t₂ i

Next tactic:
simpa [*] using h i